具有较大数组的 memcpy 段错误
memcpy segfault with larger arrays
我有一个函数可以使用 memcpy 在 C 语言中交换二维数组。我知道您可以交换指针,但我想比较一下复制数组和交换指针。
这是我的代码,二维数组是 n x n。
void swap_arrays(int n, float old[][n], float new_arr[][n]) {
float temp[n][n];
int arr_size = sizeof(float) * n * n;
memcpy(temp, old, arr_size);
memcpy(old, new_arr, arr_size);
memcpy(new_arr, temp, arr_size);
}
它适用于 5 x 5 阵列,但当阵列较大时会出现段错误(我需要的实际大小是 4000+,它在 2000+ 时开始出现段错误),在第一个 memcpy。任何帮助表示赞赏。
它有 4000 段错误,但这不是 memcpy()
的错。这是因为大小超过了你程序的堆栈大小。
尝试动态分配数组,它应该可以正常工作,像这样
float *temp;
temp = malloc(sizeof(float) * n * n);
if (temp != NULL)
{
/* memcpys here */
}
请注意,与数组不同,这不能用两个索引符号访问,要实现它,您需要像
float **temp;
temp = malloc(sizeof(float *) * n);
for (size_t i = 0 ; i < n ; ++i)
temp[i] = malloc(sizeof(float) * n); /* please check for `NULL' */
在这两种情况下您都需要 free()
,而在第二种情况下您的 memcpy()
将无法正常工作。因为temp
中的每个元素都是一个指针而不是float
,所以你需要先访问指针然后用memcpy()
复制数据。
假设你的问题是temp
太大导致的栈溢出,你可以动态分配space。因为你只是 memcpying 你不需要使用类型指针:
void swap_arrays(int n, float old[n][n], float new[n][n])
{
size_t sz = sizeof(float[n][n]);
void *buf = malloc(sz);
if ( !buf ) exit(EXIT_FAILURE);
memcpy(buf, old, sz);
memcpy(old, new, sz);
memcpy(new, buf, sz);
free(buf);
}
当然,如果您在调用代码中编写 float a[n][n];
,您也可能会遇到堆栈溢出问题。您也可以通过使用 malloc 来解决这个问题,例如:
float (*a)[n] = malloc(n * sizeof *a);
float (*b)[n] = malloc(n * sizeof *b);
如果您使用后一种方法,那么您可以 "swap" 通过交换指针,而不必复制所有数据:void *tmp = a; a = b; b = tmp;
上面的回答都很好。正如@iharod 指出的那样,您的程序超出了堆栈大小。如果您愿意,可以通过设置用户限制来增加堆栈大小。
如果您 运行 在 Linux
主机上:
alan@~$ulimit -all
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 62978
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 62978
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
如您所见,堆栈大小默认为 8192k
。
您可以使用 ulimit
命令来设置堆栈大小,例如:
alan@~$ulimit -s <stack_size_you_want>.
这仅用于说明目的,不是推荐的解决方案。
我有一个函数可以使用 memcpy 在 C 语言中交换二维数组。我知道您可以交换指针,但我想比较一下复制数组和交换指针。
这是我的代码,二维数组是 n x n。
void swap_arrays(int n, float old[][n], float new_arr[][n]) {
float temp[n][n];
int arr_size = sizeof(float) * n * n;
memcpy(temp, old, arr_size);
memcpy(old, new_arr, arr_size);
memcpy(new_arr, temp, arr_size);
}
它适用于 5 x 5 阵列,但当阵列较大时会出现段错误(我需要的实际大小是 4000+,它在 2000+ 时开始出现段错误),在第一个 memcpy。任何帮助表示赞赏。
它有 4000 段错误,但这不是 memcpy()
的错。这是因为大小超过了你程序的堆栈大小。
尝试动态分配数组,它应该可以正常工作,像这样
float *temp;
temp = malloc(sizeof(float) * n * n);
if (temp != NULL)
{
/* memcpys here */
}
请注意,与数组不同,这不能用两个索引符号访问,要实现它,您需要像
float **temp;
temp = malloc(sizeof(float *) * n);
for (size_t i = 0 ; i < n ; ++i)
temp[i] = malloc(sizeof(float) * n); /* please check for `NULL' */
在这两种情况下您都需要 free()
,而在第二种情况下您的 memcpy()
将无法正常工作。因为temp
中的每个元素都是一个指针而不是float
,所以你需要先访问指针然后用memcpy()
复制数据。
假设你的问题是temp
太大导致的栈溢出,你可以动态分配space。因为你只是 memcpying 你不需要使用类型指针:
void swap_arrays(int n, float old[n][n], float new[n][n])
{
size_t sz = sizeof(float[n][n]);
void *buf = malloc(sz);
if ( !buf ) exit(EXIT_FAILURE);
memcpy(buf, old, sz);
memcpy(old, new, sz);
memcpy(new, buf, sz);
free(buf);
}
当然,如果您在调用代码中编写 float a[n][n];
,您也可能会遇到堆栈溢出问题。您也可以通过使用 malloc 来解决这个问题,例如:
float (*a)[n] = malloc(n * sizeof *a);
float (*b)[n] = malloc(n * sizeof *b);
如果您使用后一种方法,那么您可以 "swap" 通过交换指针,而不必复制所有数据:void *tmp = a; a = b; b = tmp;
上面的回答都很好。正如@iharod 指出的那样,您的程序超出了堆栈大小。如果您愿意,可以通过设置用户限制来增加堆栈大小。
如果您 运行 在 Linux
主机上:
alan@~$ulimit -all
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 62978
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 62978
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
如您所见,堆栈大小默认为 8192k
。
您可以使用 ulimit
命令来设置堆栈大小,例如:
alan@~$ulimit -s <stack_size_you_want>.
这仅用于说明目的,不是推荐的解决方案。