我有一个应用程序,只有在使用-O1
编译时才会出现段错误
使用来自Gentoo的gcc 4.9.3和glibc 2.22-r4
(它适用于gcc 4.9.2
和来自Debian的glibc 2.19-18
。使用-O0
它可以正常工作并使用-O2
永远挂在memcpy
上。我不认为这是glibc或gcc的错误,但我
找不到我的代码有什么问题。
由于memcpy
中的堆栈溢出,似乎发生了错误。
...
Program received signal SIGSEGV, Segmentation fault.
memcpy (__dest=0x7ffff7f42010, __dest@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>, __src=0x7ffff7f91010,
__src@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>, __len=320000,
__len@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
53 return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
(gdb) where
#0 memcpy (__dest=0x7ffff7f42010, __dest@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>, __src=0x7ffff7f91010,
__src@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>, __len=320000,
__len@entry=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
#1 0x0000000000401f04 in memcpy (__dest=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__src=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__len=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
#2 0x0000000000401f04 in memcpy (__dest=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__src=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__len=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
#3 0x0000000000401f04 in memcpy (__dest=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__src=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__len=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
#4 0x0000000000401f04 in memcpy (__dest=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__src=<error reading variable: DWARF-2 expression error: Loop detected (257).>,
__len=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at /usr/include/bits/string3.h:53
---Type <return> to continue, or q <return> to quit---
...
的valgrind:
...
==2566== Stack overflow in thread 1: can't grow stack to 0xffe801ff8
==2566==
==2566== Process terminating with default action of signal 11 (SIGSEGV)
==2566== Access not within mapped region at address 0xFFE801FF8
==2566== at 0x401EFF: memcpy (string3.h:53)
==2566== If you believe this happened as a result of a stack
==2566== overflow in your program's main thread (unlikely but
==2566== possible), you can try to increase the size of the
==2566== main thread stack using the --main-stacksize= flag.
==2566== The main thread stack size used in this run was 8388608.
==2566== Stack overflow in thread 1: can't grow stack to 0xffe801ff0
==2566==
==2566== Process terminating with default action of signal 11 (SIGSEGV)
==2566== Access not within mapped region at address 0xFFE801FF0
==2566== at 0x4A246B0: _vgnU_freeres (vg_preloaded.c:58)
==2566== If you believe this happened as a result of a stack
==2566== overflow in your program's main thread (unlikely but
==2566== possible), you can try to increase the size of the
==2566== main thread stack using the --main-stacksize= flag.
==2566== The main thread stack size used in this run was 8388608.
...
在这里和那里添加一些断点我无法确定是什么
导致错误,但由于我只在一个地方调用memcpy
,我认为它是
来自那里:
/* Copy the surface b into surface a, both w x h */
static inline void
copy(double *a, double const *b, uint64_t w, uint64_t h)
{
memcpy(a, b, (size_t)(w * h) * sizeof(*a));
}
首先在这里调用:
double *surface = init(args.input[0], &w, &h);
if (!surface) {
LOG_CRITICAL("%d: %s\n", __LINE__, strerror(errno));
goto main_return;
}
double *osurface = malloc((size_t)(w * h) * sizeof(*osurface));
if (!osurface) {
LOG_CRITICAL("%d: %s\n", __LINE__, strerror(errno));
goto main_surface;
}
copy(osurface, surface, w, h);
该程序似乎没有超过copy
。
我已检查过gdb,surface
和osurface
都已成功完成
分配相同的大小。 init的代码:
/*
* Read a .pgm-like file with the initial state of the plate into a surface
* (array of doubles), dynamically allocated to the size of the image and
* returned on success. On error, nothing is allocated and NULL is returned.
* The error is registered to stderr. The size of the image is read into w,h.
* On error, this size may or may not be read into the vars.
*/
static double *
init(char const *filename, uint64_t *w, uint64_t *h)
{
double *ans = NULL;
FILE *f = fopen(filename, "r");
if (!f) {
LOG_ERROR("Could not open %s: %s\n", filename, strerror(errno));
goto init_return;
}
char mnumber[3] = { '\0' };
uint64_t ignore;
int rc = fscanf(f, " %2s %"SCNu64" %"SCNu64" %"SCNu64" ", mnumber, w, h,
&ignore);
if (rc != 4) {
LOG_ERROR("%s: Could not read header: %s\n", filename, ferror(f) ?
strerror(errno) : "EOF");
goto init_fopen;
}
if (strcmp(mnumber, IN_MNUMBER)) {
LOG_ERROR("%s: Wrong magic number: %s. Expected "IN_MNUMBER"\n",
filename, mnumber);
goto init_fopen;
}
ans = malloc((size_t)(*w * *h) * sizeof(*ans));
if (!ans) {
LOG_ERROR("%d: %s\n", __LINE__, strerror(errno));
goto init_fopen;
}
for (uint64_t i = 0; i < *w * *h; i++)
if (fscanf(f, "%lf ", ans + i) != 1) {
LOG_ERROR("%s: Reading point %"PRIu64": %s\n", filename,
i, ferror(f) ? strerror(errno) : "EOF");
goto init_malloc;
}
goto init_fopen;
init_malloc:
free(ans);
ans = NULL;
init_fopen:
fclose(f);
init_return:
return ans;
}
值得一提的是,如果我删除init
以外的所有代码,除了
malloc
该程序运行在最初的memcpy
之后
目前是segfaulting(但后来又在另一个memcpy
发生了段错误。)
可以找到包含入侵和必要输入文件的完整代码 here