【问题标题】:Disable specific compiler optimization禁用特定的编译器优化
【发布时间】:2014-08-12 15:12:17
【问题描述】:

我使用 C::B 在 Win7 的 MinGW 的 gcc 上编译了以下测试代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Func. prototype */
char* returnString (void *str);

int main()
{
    printf("%s", returnString("Hello World!!!!!!!!!!!!"));

    return 1;
}

char* returnString (void *str)
{
    char *local = malloc(strlen((char*)str));

    strcpy(local, (char*)str);

    return local;
}

默认情况下,分配会导致泄漏/u/b.. 因为我必须分配一个空闲字节+1,空终止符所在的位置。但它不会导致泄漏或崩溃,而是像空终止一样工作。有什么办法可以禁用这个吗? ..而不是使用 +1 的 5543 行代码。

【问题讨论】:

  • 这与编译器优化有什么关系?无论如何,只需使用编辑器的 grepFind in files... 在代码中找到每个 malloc 调用,然后检查并修复。最多只有几十个,所以只需要几分钟的工作时间。
  • 如果您想知道为什么它很少崩溃:malloc 甚至在 8 或 16 或类似的字节处进行关联。所以大多数时候在分配之间会有一些未使用的字节,所以缺少 +1 不会有任何影响,除了每个长度可以被某个数字整除的字符串。没有 valgrind 或分配保护字节的调试真的很讨厌。

标签: c optimization compiler-construction


【解决方案1】:

下面的行会导致 缓冲区溢出,因为在之前计算要分配的大小时缺少 + 1

    strcpy(local, (char*)str);

缓冲区溢出比内存泄漏严重得多。不幸的是,缓冲区溢出不会系统地使程序崩溃。它调用未定义的行为,这意味着任何事情都可能发生,包括程序继续运行,就好像你已经分配了一个足够大的块一样。这不是编译器优化:它可以在任何优化级别发生(或不发生),程序员几乎无法控制发生的事情。部分解决方案见下文。


获得许多缓冲区溢出诊断消息的一种方法是在正常编译程序后使用Valgrind 执行程序。

另外,最新版本的 Clang 和 GCC 包含一个“地址清理器”功能,使用-fsanitize=address 激活,在生成的代码中插入一些可能检测问题的指令。我没有使用过这个功能,但是文档是available

【讨论】:

  • 发帖者的代码实际上导致了缓冲区溢出和内存泄漏。
  • 对我来说这没什么。只是打印出文本。它必须是我必须禁用的优化。
  • @Edenia C 中的缓冲区溢出是未定义的行为。它不必导致崩溃。不导致崩溃不是优化,只是运气不好。没有简单的选项可用于告诉 GCC 生成一个在所有未定义行为上崩溃的程序,但请查看地址清理程序功能是否是您正在寻找的(-fsanitize=address 用于 GCC 4.8 或更高版本)。
  • 我知道这应该会导致缓冲区溢出。但认为有迹象表明它。不,我想我可以使用errno.h。表明这是否发生。
  • @Edenia “没有任何迹象”是什么意思?缓冲区溢出是一种无声错误,通常仅在您处于 valgrind 等正在对其进行测试的环境中时才会检测到(就像它们一样)。否则它可能在您的程序中显示为一些意外行为(可能包括看似无关的崩溃)。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 2012-02-17
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-19
相关资源
最近更新 更多