从Sun C编译器迁移到gcc

时间:2013-12-18 21:10:46

标签: c gcc solaris-10 cc

我正在研究在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编译器的差异中指出更多这样的可能的运行时错误?

2 个答案:

答案 0 :(得分:4)

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

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

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

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

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

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

char *ptr = "literal";

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

char arr[] = "literal";

使arr成为包含字符串文字的读/写副本的数组。

并且确保您问题中的代码是您正在编译的实际代码。复制并粘贴它,不要重新输入。 Please read this

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

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

你可能会在代码中发现一些有问题的东西。 -std=c99选项告诉gcc(尝试)符合1999 ISO C标准;如果您的代码要符合C90(通常但错误地称为“ANSI C”),请使用-ansi而不是-std=c99-O3选项可实现最高级别的优化;这会导致编译器执行其他分析,这也可以启用更多警告。

有许多C检查器比大多数编译器执行更多的分析。 Lint是原始工具。 Splint(以前称为LCLint)是一个现代实现,它可以通过系统的包管理器免费提供here或(可能)。

答案 1 :(得分:-1)

  

使用-Wwrite-strings并检查所有错误

可以检测到此错误
strlen(stringLiteralPointer , "anonStringLiteralValue"); 

在C中无效。我收到此错误,没有任何标记(警告):

[Error] too many arguments to function 'strlen'   
  

我们应该注意哪些其他警告可以指出更多这样的可能的运行时错误来自gcc c编译器和Sun C编译器的差异?

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