C++ 中的随机段错误

发布于 2024-08-02 13:04:58 字数 1468 浏览 4 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

人事已非 2024-08-09 13:04:58
int primes[max];

prime = primes;
while(*prime) {
    *prime = 0;
    prime++;    
}

在前面的代码中,您可以轻松地在内存中随机运行,本质上您正在遍历 RAM,直到找到 0。如果数组中没有 0,那么它将运行到不属于该进程的内存中,并且会发生段错误。

编辑:正如 Alcon 所指出的,您也在代码的其他地方执行此操作。

最好不要在堆栈上分配素数,因为您不太可能有那么多可用的堆栈内存。

要解决此问题,请尝试使用以下代码,

int primes = new int[max];

size_t count = 0;
while( count < max ) 
{
    prime[count] = 0;
    count++;    
}

并且不要忘记调用delete[] primes;在代码末尾(当您完成素数数组时)

int primes[max];

prime = primes;
while(*prime) {
    *prime = 0;
    prime++;    
}

In the preceding code you can easily run randomly through a memory, Essentially you are going through RAM until you find a 0. If there are no 0s in your array then it will run into memory that doesn't not belong to the process and a segfault will occur.

Edit: As pointed out by Alcon you are doing this in other places in your code too.

Its also best not to allocated primes on the stack as you are unlikely to have that much stack memory available.

To fix this try the following code instead

int primes = new int[max];

size_t count = 0;
while( count < max ) 
{
    prime[count] = 0;
    count++;    
}

And don't forget to call delete[] primes; at the end of your code (when you are finished with the primes array)

情丝乱 2024-08-09 13:04:58

您正在堆栈上分配数组。堆栈的大小有限并且可能溢出。

尝试使用 new/delete 分配数组。

You are allocating the array on the stack. The stack is of limited size and can overflow.

Try allocating your array using new/delete.

看透却不说透 2024-08-09 13:04:58

您应该动态分配素数数组,primes,即:

int* primes = new int[max];

您的程序甚至不应该按原样编译。祝你作业顺利!

You should be dynamically allocating your array of primes, primes, i.e:

int* primes = new int[max];

Your program shouldn't even compile as is. Good luck with your homework!

皇甫轩 2024-08-09 13:04:58

一方面,这是有问题的:

int sum_array(int num_array[]) {
    int current_total = 0;
    int *iptr = num_array;
    while(*iptr) {
        current_total += *iptr;
        iptr++;
    }
    return current_total;
}

这表示从给定数组的开头开始。当 int 大小的内存块中的值不为零时,移动到下一个内存块。这里发生的情况是,它会继续越过数组的末尾,最终扰乱内存,这不应该扰乱内存,这就是导致段错误的原因。它看起来随机的原因是有时数组末尾的内存是空的,这会正常工作。但有时情况并非如此,然后它会访问不应该访问的内存并崩溃。

这可能不是唯一的问题,但这是我注意到的第一个问题。要修复此问题,请跟踪数组的大小,将其传递给函数,然后使用 for 循环迭代它,而不是使用指针。就像这样:

int sum_array(int num_array[], int arraySize) {
    int current_total = 0;
    for(int i = 0; i < arraySize; i++) {
        current_total += num_array[i];
    }
    return current_total;
}

我再看看还有没有其他的。

编辑:

再看一遍,您在另外两个地方做了同样的事情。这里:

while(*prime) {
        cout << *prime << " ";
        prime++;
    }

和这里:

while(*prime) {
    *prime = 0;
    prime++;    
}

在这两个地方,我敢打赌,你的数组超出了范围,这就是导致段错误的原因。如果您是新手,我强烈建议您不要使用指针算术来遍历数组。坚持使用旧的 for 循环并跟踪 for 循环的结尾。

其他人建议从堆而不是堆栈中分配数组。对于一个巨大的数组来说,这是一个好主意,但是,至少根据我的经验,堆栈溢出通常不会导致段错误。当您分配的空间多于堆栈中的空间时,编译器通常会注意到。尽管如此,我还是建议使用向量(为了给你的家庭作业带来额外的加分,看看你是否能弄清楚如何使用分配为堆中指针数组的双指针来实现你自己的向量;))或者只使用std: :向量。它是一个可扩展的数组,当您找到质数时,可以将它们添加到数组中,而不是分配大量您不一定需要的空间。

Well for one thing, this is problematic:

int sum_array(int num_array[]) {
    int current_total = 0;
    int *iptr = num_array;
    while(*iptr) {
        current_total += *iptr;
        iptr++;
    }
    return current_total;
}

What this says is start at the beginning of the array you are given. While the value in a memory block the size of an int isn't zero, move to the next memory block. What happens here is it'll keep going past the end of your array, eventually messing with memory it shouldn't which is what causes the segfault. The reason it seems random is that sometimes the memory at the end of the array IS empty, and this'll work fine. But sometimes it's not, and then it accesses memory it shouldn't and CRASH.

That might not be the only problem but it was the first one I noticed. To fix it, keep track of the size of your array, pass it to the function, and then use a for loop to iterate up to it rather than using pointers. Like this:

int sum_array(int num_array[], int arraySize) {
    int current_total = 0;
    for(int i = 0; i < arraySize; i++) {
        current_total += num_array[i];
    }
    return current_total;
}

I'll look again to see if there's anything else.

Edit:

On a second look, you do the same thing in two other places. Here:

while(*prime) {
        cout << *prime << " ";
        prime++;
    }

And here:

while(*prime) {
    *prime = 0;
    prime++;    
}

In both places I'd bet dollars to donuts you are overrunning your array and that's what's causing the segfaults. If you're new I'd strongly recommending against using pointer arithmetic to traverse your arrays. Stick to good old for loops and keep track of the end of the for loops.

Other folks have suggested allocating the array from the heap instead of the stack. That's a good idea for a huge array, however, in my experience at least, stack overruns don't usually cause segfaults. The compiler will usually notice when you allocate more space than is in the stack. Still I'd suggesting using a vector (for big extra credit on your homework see if you can figure out how to implement your own vector using a double pointer allocated as an array of pointers from the heap ;) ) or just use the std::vector. It's an expandable array and that will let you add primes to your array as you find them rather than allocating a whole ton of space that you don't necessarily need.

妄想挽回 2024-08-09 13:04:58

戈兹指出事情很早就开始出错。

初学者很容易犯错误,但即使是老手也会犯同样的错误。为此,退伍军人制作了出色的程序来自动查找问题:

免费程序包括 lint,它会在运行代码之前检查代码,而且 - 更好 - valgrind 它会在您运行代码时检查代码!在 Windows 上,还有其他商业替代方案,例如 Purify

即使对于经验丰富的老手来说,在开发过程中通过 valgrind 和静态代码检查器运行程序,以及使用编译器启用的所有警告进行编译,也是开发卫生的一部分。

Goz has pointed out how early things start going wrong.

Its easy for beginners to make mistakes, but even veterans make exactly the same mistakes. For this reason, veterans have made excellent programs for automatically finding the problems:

Free programs include lint, which examines code before you run it, and - even better - valgrind which examines code as you run it! On Windows, there are other commercial alternatives like Purify.

Running programs during development via valgrind and static code checkers, as well as compiling with all warnings enabled from the compiler, is part of development hygiene even for seasoned veterans.

南巷近海 2024-08-09 13:04:58

其他人(例如 Goz)提供了正确的答案 - 不能依赖未初始化变量的值,因为它们在每次运行时都会有所不同。正如其他人指出的那样,在堆栈上分配大型数组也是有风险的,因为堆栈空间通常比堆空间更稀缺。

作为一个附带问题,以 primes[max] 的方式分配可变大小的数组不是符合标准的 C++,而是 g++ 扩展,因此您的代码不太可能与其他编译器一起工作。您可以使用 newdelete 来代替 - 但在这些情况下最好养成使用 vector 的习惯,因为它将为您进行清理工作。

[编辑:感谢威尔指出问题的真正根源在其他地方。]

Others (e.g. Goz) have provided the correct answer -- the values of uninitialised variables cannot be relied on as they vary from run to run. As others have pointed out, it's also risky to allocate large arrays on the stack as stack space is usually more scarce than heap space.

As a side issue, allocating arrays of variable size in the way that you are with primes[max] is not standard-compliant C++, but rather a g++ extension, so your code as it stands is unlikely to work with other compilers. You could use new and delete instead -- but it's even better to get into the habit of using vector<int> in these situations since it will do the cleanup for you.

[EDIT: Thanks Will for pointing out that the real root cause of trouble was elsewhere.]

逆流 2024-08-09 13:04:58
int primes[max];

在堆栈中分配巨大的数组是不好的,因为默认情况下堆栈的大小很小。最好在堆中分配 primes[]。

int primes[max];

Allocating huge arrays in the stack is bad because stacks, by default, have small size. It's better to allocate primes[] in the heap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文