17

以下の短いコード (文字列を定義し、strdup を使用してコピーを作成) をコンパイルすると、3 つの警告が表示されます。GCC からの 2 つのコンパイラ警告と、valgrind からの 1 つのランタイム警告/エラーです。

メモリ リーク エラー (valgrind によって報告された) も、strdup の使用に関連していると思われるため、関連する出力を以下に示します。

私は何を間違っていますか?(私はCの本を読んでいますが、これが著者によるstrdupの使用方法です。)


コード:

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
  char *string1 = "I love lamp";
  char *string2;

  string2 = strdup(string1);

  printf("Here's string 1: %s\n"
     "Here's string 2: %s\n",
     string1, string2);

  return 0;
}

警告/出力:

dchaudh@dchaudhUbuntu:~/workspaceC/LearnCHW/Ex17_StructsPointers$ make test
cc -std=c99    test.c   -o test
test.c: In function ‘main’:
test.c:9:3: warning: implicit declaration of function ‘strdup’ [-Wimplicit-function-declaration]
   string2 = strdup(string1);
   ^
test.c:9:11: warning: assignment makes pointer from integer without a cast [enabled by default]
   string2 = strdup(string1);
           ^
dchaudh@dchaudhUbuntu:~/workspaceC/LearnCHW/Ex17_StructsPointers$ valgrind --track-origins=yes --leak-check=full ./test
==3122== Memcheck, a memory error detector
==3122== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3122== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==3122== Command: ./test
==3122== 
Here's string 1: I love lamp
Here's string 2: I love lamp
==3122== 
==3122== HEAP SUMMARY:
==3122==     in use at exit: 12 bytes in 1 blocks
==3122==   total heap usage: 1 allocs, 0 frees, 12 bytes allocated
==3122== 
==3122== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3122==    at 0x4C2ABBD: malloc (vg_replace_malloc.c:296)
==3122==    by 0x4EBF2B9: strdup (strdup.c:42)
==3122==    by 0x4005A4: main (in /home/dchaudh/workspaceC/LearnCHW/Ex17_StructsPointers/test)
==3122== 
==3122== LEAK SUMMARY:
==3122==    definitely lost: 12 bytes in 1 blocks
==3122==    indirectly lost: 0 bytes in 0 blocks
==3122==      possibly lost: 0 bytes in 0 blocks
==3122==    still reachable: 0 bytes in 0 blocks
==3122==         suppressed: 0 bytes in 0 blocks
==3122== 
==3122== For counts of detected and suppressed errors, rerun with: -v
==3122== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
4

4 に答える 4

35

C 標準ライブラリには のような機能はありませんstrdup。それにもかかわらず、この人気のある関数は通常、標準ライブラリの実装によって拡張機能として提供されます。GCC 実装では、この関数は で宣言されており<string.h>、これを含めます。

ただし、 のように、より厳密な標準設定でコードをコンパイルすると-std=c99、コンパイラは標準ライブラリ ヘッダーで作成された非標準関数宣言を非表示にします。strdupこれは、あなたの場合の宣言に起こったことです。表示される警告は、宣言されていない関数を呼び出そうとしたときに発行される典型的な警告です。正式には、これは C99 の観点からはエラーですが、この場合は警告で十分であるとコンパイラが判断しました。-std=c99コンパイラのコマンド ラインからスイッチを削除すると、の宣言strdupが表示され、コードはその警告なしでコンパイルされます。

より技術的に-std=c99は、コマンドラインで指定すると、GCC が__STRICT_ANSI__マクロを定義し、ANSI 以外のすべての関数宣言が標準ヘッダーから「消えます」。

関数はライブラリにまだ存在するため、コードが適切にリンクされます。実際にはポインタを返すのに、コンパイラは が を返すと想定しているため、必ずしも正しく実行されるとは限らないことに注意してください。strdupint

valgrind レポートは、メモリ リークの結果です。必要がなくなったときに、strdup想定されているメモリを自分自身に割り当てます。free

于 2014-10-09T17:10:16.017 に答える
12

strdup() は標準 Cではありません。これは POSIX 拡張です。

オプションをstrdup()使用するときに GCC の厳密な C99 準拠でも利用できるようにするには、少なくとも次のいずれ-std=c99かが必要です。#define

_SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500 
  || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
  || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

(strdup()の Linux man-pageから取得)

たとえば、次のようにコーディングします (を含める前に<string.h>):

#define _SVID_SOURCE

また:

#define _POSIX_C_SOURCE 200809L

あるいは、オプションとして GCC のコマンドライン経由でこれらの定義を渡すことができます

-D_SVID_SOURCE

また

-D_POSIX_C_SOURCE=200809L
于 2014-10-09T18:28:53.733 に答える
-3

宣言するヘッダー ファイルを #include しなかったため、コンパイラには strdup の宣言がありません。

宣言がないため、コンパイラは strdup が int を返すと推測しました。strdup を呼び出した結果をポインター変数に代入します。

適切なヘッダー ファイルをインクルードすれば、少なくとも問題は少なくなるはずです。

于 2014-10-09T17:10:42.417 に答える