2014-10-09 86 views
0

當我編譯下面的短片段(在其中我們定義一個字符串,然後使用strdup做一個副本),我得到3個警告:來自GCC的2個編譯器警告和來自valgrind的1個運行時警告/錯誤。strdup():困惑於警告('隱式聲明','使指針...沒有投射',內存泄漏)

我懷疑內存泄漏錯誤(由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; 
} 

的警告/輸出:

[email protected]:~/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); 
     ^
[email protected]:~/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) 
+0

您還沒有爲'strdup'相關的頭通過GCC的命令行的定義。 – 2014-10-09 17:09:12

+0

他做到了。 @OliverCharlesworth – alk 2014-10-09 17:17:35

回答

9

C標準庫不具備strdup等功能。儘管如此,這種流行的功能通常由標準庫實現作爲擴展來提供。在GCC實現中,這個函數在<string.h>中聲明,你包含它。

但是,當您使用更嚴格的標準設置(如-std=c99)編譯代碼時,編譯器將隱藏標準庫標頭中生成的非標準函數聲明。這就是你的情況下strdup聲明發生的情況。您收到的警告是當您嘗試調用未聲明的功能時發出的典型警告。從C99的角度來看,這是一個錯誤,但是你的編譯器決定在這種情況下警告就足夠了。如果從編譯器的命令行中刪除-std=c99開關,則strdup的聲明將變爲可見,並且代碼將在沒有該警告的情況下編譯。

更具體地說,在命令行中指定-std=c99使GCC定義了__STRICT_ANSI__宏,這將導致所有非ANSI函數聲明從標準頭文件中「消失」。

函數仍然存在於庫中,這就是爲什麼你的代碼正確鏈接。請注意,它不一定正常運行,因爲編譯器假定strdup返回了int,實際上它返回一個指針。

valgrind報告只是內存泄漏的後果。 strdup分配內存,當你不再需要時你應該自己free

+0

可能要補充的是,當程序結束時,有足夠的理由讓內存釋放,但這些不適用於試圖學習該語言的初學者。 – Deduplicator 2014-10-09 17:14:18

+1

+1「雖然['strdup()'](http://linux.die.net/man/3/strdup)在''中聲明,它不是*提供的標準C庫函數。」 Sry,我很難解析第一句話。 – WhozCraig 2014-10-09 17:14:40

+2

「真實」的參考:http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html @WhozCraig – alk 2014-10-09 17:16:52

-2

你的編譯器沒有聲明strdup,因爲你沒有#include任何頭文件聲明它。

沒有聲明,編譯器猜測strdup會返回一個int。您將調用strdup的結果分配給一個指針變量。

包含正確的頭文件,你的問題應該至少得到更少。

+2

根據OP的消息來源' **'包含**。 – alk 2014-10-09 17:14:24

3

strdup()不是標準C. It is a POSIX extension。(從strdup()'s Linux man-page拍攝)

通過

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

要使用你需要以下的#define至少一個選項-std=c99時使即使有嚴格C99遵守海合會可用strdup()編碼例如(在包括<string.h>之前):

#define _SVID_SOURCE 

或:

#define _POSIX_C_SOURCE 200809L 

Alternativly你可以通過爲選項

-D_SVID_SOURCE 

-D_POSIX_C_SOURCE=200809L 
+0

最後的「200 ** 9 ** 09L」是一個錯誤,對吧?我猜它應該是「200809L」。 – hmijail 2017-02-02 12:28:57

+0

@hmijail絕對!感謝您的通知。固定。 – alk 2017-02-02 17:46:24