【问题标题】:Getting a segmentation fault when running Release version, but not Debug version in Code Blocks在运行发布版本时出现分段错误,但在代码块中没有调试版本
【发布时间】:2016-04-14 16:38:28
【问题描述】:

我正在使用代码块:

Release 13.12 rev 9501 (2013-12-25 18:25:45) gcc 4.8.2 Linux/unicode - 64 bit

在以下系统上:

Linux Mint 17.3 Cinnamon (version 2.8.7) 64-bit
Intel Core i7-4790
NVIDIA GeForce GTX 750 Ti

当我将选定的目标设置为“调试”并运行我的代码时,它运行良好。我已经运行了很多次,没有任何问题。但是当我选择“发布”目标并从命令提示符运行程序时,经常会出现分段错误。

我的 C++ 程序大约有一千行,我不知道程序的哪一部分导致了分段错误。所以我不知道现阶段哪些代码是相关的(当我有更多信息时,我会在这里发布一些代码)。它确实利用了指针和动态数据结构。我猜有些东西没有正确初始化,但我不知道如何调试“发布”版本。我没有从默认值更改任何编译器或链接器设置。 “发布”版本中可能有什么不同会导致此问题?

(更新)按照 Nathan 的建议,我能够隔离分段错误。有一个 for 循环,但在某些情况下,此循环的上限(结束索引)没有被初始化,如下所示:

void fnProc(bool var_val, int inp_val, int test_val, int st_idx, int lim_idx, int xarr[])
{
    int idx, end_idx;
    if (test_val > inp_val)
        end_idx = someFn(inp_val, lim_idx, xarr);
    if (!var_val)
        for (idx = st_idx; idx <= end_idx; idx++)
            xarr[idx] = 0;
}

我能够通过将“end_idx”变量初始化为零(“st_idx”总是大于一)来解决这个问题:

void fnProc(bool var_val, int inp_val, int test_val, int st_idx, int lim_idx, int xarr[])
{
    int idx, end_idx;
    if (test_val > inp_val)
        end_idx = someFn(inp_val, lim_idx, xarr);
    else
        end_idx = 0;
    if (!var_val)
        for (idx = st_idx; idx <= end_idx; idx++)
            xarr[idx] = 0;
}

当变量没有像这样初始化时,是否可以让代码块/GCC 编译器发出警告?我看到有一个 GCC 选项:-Wuninitialized,但我在代码块中没有看到这个。

【问题讨论】:

  • 使用一些cout 语句来标记代码块。一旦出现故障,您至少应该知道它是从哪个块中识别出来的,然后再从那里缩小范围。但你是对的。这很可能意味着您的代码中有某种 UB。

标签: c++ linux gcc codeblocks


【解决方案1】:

是否有可能让代码块/GCC 编译器在变量时发出警告 还没有这样初始化?我看到有一个 GCC 选项:-Wuninitialized, 但我在代码块中没有看到这个

您可以添加编译器设置 -> 编译器标志中不可用的任何编译器选项 从工作区树形视图导航菜单您的项目 -> 构建选项 -> {Debug|Release} -> 编译器设置 -> 其他编译器选项 并在文本框中列出它们。

但是,没有必要以这种方式添加-Wuninitialized,因为它 由-Wall 启用,并由您的代码使用通常的发布版本触发 优化-O2(或任何高于-O0):-

foo.cpp

extern int someFn(int, int, int[]);

void fnProc(bool var, int inp_val, int test_val, int st_idx, int lim_idx, int xarr[])
{
    int idx, end_idx;
    if (test_val > inp_val)
        end_idx = someFn(inp_val, lim_idx, xarr);
    if (!var)
        for (idx = st_idx; idx <= end_idx; idx++)
            xarr[idx] = 0;
}

使用 g++ 5.2:

$ g++ -O2 -Wall -c foo.cpp
foo.cpp: In function ‘void fnProc(bool, int, int, int, int, int*)’:
foo.cpp:5:14: warning: ‘end_idx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     int idx, end_idx;
              ^

这至少可以追溯到 GCC 4.4.7

-Wall 从 Code::Blocks 编译器设置 -> 编译器标志菜单启用 通过勾选项目 Warnings -> 启用所有常见的编译器警告

在 Code::Blocks 16.01(我目前拥有的)中,即使这个设置也是不必要的 因为-Wall 默认为调试和发布配置启用, 因此警告正式出现在默认 Code::Blocks 控制台项目发布版本中 foo.cpp:-

-------------- Build file: Release in deleteme (compiler: GNU GCC Compiler 5.2)---------------

g++-5 -Wall -fexceptions -O2  -c /home/imk/develop/deleteme/foo.cpp -o obj/Release/foo.o
/home/imk/develop/deleteme/foo.cpp: In function ‘void fnProc(bool, int, int, int, int, int*)’:
/home/imk/develop/deleteme/foo.cpp:5:14: warning: ‘end_idx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     int idx, end_idx;
              ^
Process terminated with status 0 (0 minute(s), 0 second(s))
0 error(s), 1 warning(s) (0 minute(s), 0 second(s))

据我所知,-Wall 一直是 GCC 的默认选项 Code::Blocks 用了 6 年左右,但也许我弄错了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    相关资源
    最近更新 更多