strdup出现隐式声明警告与段错误的原因是什么?
问题描述
开发时发现strdup函数表现异常,涉及三个文件:
foo.h
#ifndef FOO_H #define FOO_H void example(char *a); #endif //FOO_H
foo.c
#include <stdio.h> #include <stdlib.h> #include "foo.h" void example(char *a) { if (a == NULL) { fprintf(stderr, "a is NULL"); exit(1); } char *temp = strdup(a); printf("%s", temp); }
bar.c
#include <stdio.h> #include <stdlib.h> #include "foo.h" int main() { char *a = "Hello World "; example(a); return 0; }
编译时出现以下警告:
foo.c:10:18: warning: implicit declaration of function ‘strdup’ [-Wimplicit-function-declaration] foo.c:10:18: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
运行程序触发段错误,已知解决方案为不使用C11标准编译,或自行在头文件声明strdup,询问问题产生的原因。
问题原因分析
strdup的标准归属限制:strdup不是C标准库函数(C11及更早的C标准均未收录),它是POSIX标准定义的扩展函数。当以C11标准编译时,编译器严格遵循C标准规范,此时stdlib.h不会包含strdup的函数声明。- 隐式声明的类型不匹配:编译器遇到未声明的
strdup时,会触发隐式声明规则,默认该函数返回int类型。但实际strdup的返回值是char*指针,将int类型值赋值给char*变量会导致指针地址被错误转换(64位系统中int长度通常小于指针长度,会造成地址截断)。 - 段错误的直接触发点:错误转换后的非法指针
temp,在printf中被当作有效字符串地址访问,会直接触发非法内存访问,最终导致段错误。 - 非C11编译可行的逻辑:不指定C11标准时,编译器会启用兼容POSIX扩展的宽松模式,此时
stdlib.h会包含strdup的声明,隐式声明和类型转换的问题自然消失。
内容的提问来源于stack exchange,提问作者demon
相关产品推荐
相关产品推荐

