0

为了与我们的其他程序保持一致,我正在研究在 Solaris 10 机器上从 Sun C 5.9 迁移到 gcc (GCC) 3.4.6 可能存在的缺陷。是否有任何我们应该注意的指南或可能的陷阱列表?

我们已经用以下类型的代码缩小了问题的范围(我们知道这是不好的做法,但长期存在):

char* stringLiteralPointer = "someStringLiteralValue";
strcpy(stringLiteralPointer , "anonStringLiteralValue"); //Crash here only with gcc

可以通过使用 -Wwrite-strings 并检查所有错误来检测此错误。是否还有其他我们应该注意的警告可以从 gcc c 编译器和 Sun C 编译器的差异中指出更多此类可能的运行时错误?

4

2 回答 2

4

strlen函数只接受一个类型的参数const char*(这意味着它将接受一个非const char*参数)。

一些较旧的编译器可能会接受参数数量不正确的函数调用。您需要修复代码。

这是假设您的代码实际使用strlen. 正如 fernando.reyes 在评论中所建议的那样,您可能真的是指strcpy而不是strlen(特别是因为您不使用结果;调用strlen()和丢弃结果没有多大意义)。

在这种情况下,问题在于stringLiteralPointer指向(关联的数组对象)字符串文字。尝试修改此类数组具有未定义的行为。一些编译器可能会将字符串文字放入读/写内存中,但您不应该依赖它。

同样,解决方案是修复您的代码。您需要安排 forstringLiteralPointer指向一个不是字符串文字的数组。一种方法是使用malloc分配足够的空间(并确保检查返回的指针malloc是非空的)。如果您的指针已经指向字符串文字,您可能还可以使用非标准strdup函数,该函数(尝试)分配字符串的新读/写副本并返回指向它的指针。同样,您需要确认分配成功。

另一种选择可能是使用数组,而不是指针。这个:

char *ptr = "literal";

导致ptr指向不允许修改的字符串。这个:

char arr[] = "literal";

创建arr一个包含字符串文字的读/写副本的数组。

确保您问题中的代码是您正在编译的实际代码。复制粘贴,不要重复输入。请阅读此

更一般地说,gcc 有许多选项可以启用额外的警告。如果您使用以下内容编译代码:

gcc -std=c99 -Wall -Wextra -O3 ...

您可能会在代码中发现许多有问题的东西。该-std=c99选项告诉 gcc (尝试)符合 1999 ISO C 标准;如果您的代码旨在符合 C90(通常但不正确地称为“ANSI C”),请使用-ansi而不是-std=c99. 该-O3选项可实现最大程度的优化;这会导致编译器执行额外的分析,也可以启用更多警告。

有许多 C 检查器可以执行比大多数编译器更多的分析。Lint是最初的工具。Splint(以前称为 LCLint)是一种现代实现,可以在这里免费获得,或者(可能)通过系统的包管理器获得。

于 2013-12-18T21:18:09.847 回答
-1

可以通过使用 -Wwrite-strings 并检查所有错误来检测此错误

strlen(stringLiteralPointer , "anonStringLiteralValue"); 

在 C 中无效。我在没有任何标志(警告)的情况下收到此错误:

[Error] too many arguments to function 'strlen'   

是否还有其他我们应该注意的警告可以从 gcc c 编译器和 Sun C 编译器的差异中指出更多此类可能的运行时错误?

-Wall在 GCC 中,要检测更多警告,您可以使用和-Wextra标志在 C99 模式 (-std=C99) 下编译代码。

于 2013-12-18T21:14:24.807 回答