2014-10-09 83 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