当我编译下面的一小段代码(我们在其中定义一个字符串,然后使用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)
答案 0 :(得分:14)
C标准库没有strdup
这样的功能。然而,这种流行的功能通常由标准库实现作为扩展提供。在GCC实现中,此函数在<string.h>
中声明,您可以包含它。
但是,当您使用更严格的标准设置(如-std=c99
)编译代码时,编译器会隐藏标准库头中的非标准函数声明。这就是你案件中strdup
声明发生的事情。您收到的警告是当您尝试调用未声明的函数时发出的典型警告。从形式上看,从C99的角度来看,这是一个错误,但是在这种情况下,您的编译器确定警告就足够了。如果从编译器的命令行中删除-std=c99
开关,strdup
的声明将变为可见,代码将在没有该警告的情况下编译。
从技术上讲,在命令行中指定-std=c99
会使GCC定义__STRICT_ANSI__
宏,这会导致所有非ANSI函数声明从标准头中“消失”。
该函数仍然存在于库中,这就是您的代码正确链接的原因。请注意,它不一定正确运行,因为编译器假定strdup
返回int
,而实际上它返回一个指针。
valgrind报告只是内存泄漏的结果。当你不再需要时,strdup
会自己分配free
你自己的内存。
答案 1 :(得分:4)
strdup()
不是标准C. It is a POSIX extension。
在使用选项-std=c99
时,即使GCC严格遵守C99,也要strdup()
可用,您需要#define
至少以下其中一项:
_SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500
|| _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
通过编码举例(包括<string.h>
之前):
#define _SVID_SOURCE
或:
#define _POSIX_C_SOURCE 200809L
另外,您可以通过GCC的命令行作为选项
传递这些定义-D_SVID_SOURCE
或
-D_POSIX_C_SOURCE=200809L
答案 2 :(得分:0)
正如AnT已经说过的那样,当您使用标志“ -std = c99”时,编译器会在标头“ string.h”中隐藏所有非标准函数
一种解决方法是在代码的开头(或您想要的任何地方,只要在使用strdup函数之前)添加此行代码
extern char* strdup(const char*);
答案 3 :(得分:-2)
您的编译器没有strdup声明,因为您没有#include声明它的任何头文件。
没有声明,编译器猜测strdup会返回一个int。您将调用strdup的结果分配给指针变量。
包含正确的头文件,您的问题至少应该减少。