【问题标题】:Segmentation fault(core dumped) variable assignment分段错误(核心转储)变量分配
【发布时间】:2014-02-02 21:24:22
【问题描述】:

我有一个用 C++ 编写的程序,用 G++ 编译,在 Ubuntu 13.04 32 位中运行,它给出了以下错误:“Segmentation fault (core dumped)”。

int main(int argc, char *argv[]){
printf("1\n");
int x = 0 , y = 0, count = 0;
printf("2\n");
char c;
printf("3\n");
int n_frames = (atoi(argv[1]) - 1);
printf("4\n");
int windowSize = WINDOW_SIZE; // WINDOW_SIZE is a define
printf("5\n");
// And the program go on....

long double frames[n_frames][377];

long double dis_frames[n_frames - (windowSize - 1)];
int tam_dis_frames = n_frames - (windowSize - 1);
long double white_top_hat[tam_dis_frames];

当“n_frames”值(由 argv[1] 带来的值)较低(测试到 300)时,不会发生错误并且一切正常。

当值更高(如 1922)时,会发生错误。当错误发生时,显示的最后一个 printf 是第四个 printf("4\n")"。

当值为 1853 或更低时,会显示 "printf("5\n")" 但不会显示下一个 printf。

有人知道什么可以解决吗?在如此简单的程序步骤中,分段错误(核心转储)的来源可能是什么......

【问题讨论】:

  • 如何启动该程序?也就是说,什么是 argv[1]
  • 您提供什么输入? Printg argc 和 argv 用于诊断。另外,假装你从未听说过 atoi 和 printf 并学习 C++。
  • 调试此类问题的第一步是尝试使用 minimal 程序重现错误。例如。在这种情况下,请尝试删除 int n_frames... 之前的所有语句。错误还会出现吗?
  • last printf 未显示,因为它已被执行,但它在缓冲区中准备打印。但是段错误不在此代码中,请添加更多代码。
  • 程序执行如下:./Program.exe 1922

标签: c++ variable-assignment


【解决方案1】:

您的frames 数组是使用用户在命令行中传入的动态大小在堆栈上创建的。您已经超出了标准 C++ 领域,并使用了称为“可变长度数组”的扩展/C99ism。

此外,您传入的 n_frames 值 (1922) 使帧数组的长度为 1922*377*10 字节,即大约 7.5 MB。在几乎任何标准台式机/笔记本电脑/操作系统上,您的堆栈大小限制大约为 1MB,因此您在两种不同的方面被破坏了。

解决您的问题的显而易见的直接方法是像这样动态分配frames

long double** frames = new (long double*)[n_frames];
for (int i = 0; i < n_frames; ++i) {
  frames[i] = new long double[377];
}

...当然不要忘记最后对应的delete []

不过,话虽如此,您可能想了解 std::vector 作为 C++ 中事实上的动态分配数组类。

【讨论】:

  • 谢谢,这行得通,但在程序的其他部分出现了分段错误。我想我需要学习更多的 C/C++ 来了解这些内存分配是如何工作的。
  • @dragons 你应该避免原始分配
【解决方案2】:

这是堆栈溢出。您正在使用许多可变长度数组 (VLA),并且对于较大的 n_frames 值,您会溢出堆栈。改为使用动态分配的内存。

我怀疑您甚至没有意识到您正在使用 VLA。它们是一个很容易被滥用的功能,除非您真正了解使用它们的全部含义,否则您应该避免使用它们。

您的代码看起来更像 C 而不是 C++。在我看来,是时候学习如何以 C++ 的方式做事了。你真的应该避免原始内存分配。你当然不应该调用 printf 并且永远不要调用 atoi。

【讨论】:

    猜你喜欢
    • 2015-06-25
    • 2021-06-03
    相关资源
    最近更新 更多