c-排序时出现分段故障-Malloc



我正在读取一个浮点数文件,然后对它们进行排序。当我对100万个数字使用以下排序和交换函数时,我能够成功地对数字进行排序。然而,当我试图对1亿个数字进行排序时,我会遇到分段错误。我不知道为什么,因为我在动态分配内存。我该如何处理超过100万个数字?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void swap(float *a, float *b, size_t n) {
size_t numbytes; 
size_t sz = sizeof(float); 
void *temp = NULL; 

numbytes = n * sz; 
if (numbytes == 0){
exit(EXIT_FAILURE); 
}
temp = malloc(numbytes);

memcpy(temp, a, numbytes);
memcpy(a,b,numbytes); 
memcpy(b,temp,numbytes);

free(temp); 
}
void radixSort(float array[], size_t count) {
int numOfZero = 0; 
float a[count];
float *b = a;

for (uint32_t radix=1; radix; radix<<=1) { //unsigned int 32 bit
uint32_t *arrayToInt = (uint32_t *)array;
int zeroCount=0;
int oneCount=0;
numOfZero=0;

for (int j=0; j < count; ++j)
numOfZero += !(arrayToInt[j]&radix);
oneCount=numOfZero;

for (int j=0; j < count; ++j)
if (arrayToInt[j]&radix){
b[oneCount]=array[j];
++oneCount;
}
else{
b[zeroCount]=array[j];
++zeroCount;
}
swap(b,array,count);
}
if (numOfZero < count){
memcpy(b+(count-numOfZero), array, numOfZero*sizeof(float));

for (int d=0,j=count-1;j>=numOfZero;j--,d++)
b[d]=array[j];
memcpy(array, b, count*sizeof(float));
}
}
int main(int argc, char *argv[]) {
int fd; 
float num; 
size_t nr; 
int eleNum = 0; 

fd = open(argv[1], O_RDONLY); 

if (fd == -1){
perror("Error opening file");
exit(EXIT_FAILURE);
}

struct stat st; 
fstat(fd, &st); 
off_t size = st.st_size; 
for (int j = 0; j < size/4; j++){
eleNum++; 
} 

float array[eleNum];
for (int i = 0; i < eleNum; i++){
nr = read(fd, &num, sizeof(float));
if (nr == -1){
perror("Error reading file"); 
exit(EXIT_FAILURE); 
}
array[i] = num; 
}

radixSort(array, eleNum);

close(fd); 
return 0; 
}

这些行:

float a[count]; // In radixSort
float array[eleNum]; // In main

永远不会为这么大的数字工作。VLA:s(通常并且在实践中总是(在堆栈上分配。在Windows系统上,堆栈通常为1MB,在Linux上为8MB。我已经写了一个关于VLA:s的答案,你读一下会很好。简而言之,我建议不要使用它们。我真的需要malloc吗?

我不确定更改为malloc是否能解决你的问题,但如果不这样做,你就无法解决它。

此外,您应该检查malloc的返回值,看看分配是否有效。然后,如果您的问题仍然存在,我建议您使用-Wall -Wextra -pedantic -std=c11 -fsanitize=address -g进行编译。使用gdb或其他调试器查找导致segfault的行并调查值。使用valgrind检测内存泄漏。

这个:

for (int j = 0; j < size/4; j++){
eleNum++; 
} 

这很奇怪。它相当于eleNum = size/4

swap:中

if (numbytes == 0){
exit(EXIT_FAILURE); 
}

完全没有必要。将size参数的0传递给memcpy是安全的。这只会导致什么都没发生。出于调试目的,我可以理解这一点,但在这种情况下,您应该打印一些有用的东西,或者更好的是,使用assert(numbytes > 0)

相关内容

  • 没有找到相关文章

最新更新