相同循环和数组中的隔离错误

Segfault in Identical Loops and Arrays

本文关键字:隔离 错误 数组 循环      更新时间:2023-10-16

因此,我以完全相同的方式声明两个 2D 浮点数组。

float** a1 = new float*[chunk_size];
for (i = 0; i < chunk_size; ++i) {
    a1[i] = new float[chunk_size];
}
float** a2 = new float*[chunk_size];
for (i = 0; i < chunk_size; ++i) {
    a2[i] = new float[chunk_size];
}

然后继续访问第一个,然后是第二个...

for (i = 0; i < chunk_size; ++i) {
    for (j = n = m = d = 0; j < chunk_size; j = m) {
        do {
            std::cout << "i: " << i << " m: " << m << std::endl;
            d = a1[i][m]; <-----------NO-SEGFAULT
            ++m;
        } while (d != 0 && m < chunk_size);
        delta = (d - a1[i][j]) / m;
        n = j + 1;
        while (n < j + m) {
            a1[i][n] = a1[i][n - 1] + delta;
            ++n;
        }
    }
}

在第二个循环集上,我在第一次迭代中得到一个段错误。

for (j = 0; j < chunk_size; ++j) {
    for (i = n = m = d = 0; i < chunk_size; i = m) {
        do {
            std::cout << "m: " << m << " j: " << j << std::endl;
            d = a2[m][j]; <--------------SEGFAULT
            ++m;
        } while (d != 0 && m < chunk_size);
        delta = (d - a2[i][j]) / m;
        n = i + 1;
        while (n < i + m) {
            a2[n][j] = a2[n - 1][j] + delta;
            ++n;
        }
    }
}

除非我错过了什么,或者没有分享其他重要的东西,否则我看不出是什么原因导致一个而不是另一个。

作为参考,i、j、n、m 和 chunk_size 属于 size_t 型,而 delta 和 d 属于 float 型。

编辑:控制台输出

 i: 255 m: 248
 i: 255 m: 249
 i: 255 m: 250
 i: 255 m: 251
 i: 255 m: 252
 i: 255 m: 253
 i: 255 m: 254
 i: 255 m: 255
 m: 0 j: 0
 Segmentation fault

瓦尔格林德乌普特

i: 255 m: 250
i: 255 m: 251
i: 255 m: 252
i: 255 m: 253
i: 255 m: 254
i: 255 m: 255
m: 0 j: 0
==3518== Use of uninitialised value of size 8    ==3518==    at 0x403240: WSUMap::blockTypeIDAt(unsigned int, unsigned int, unsigned int) const (WSUMap.h:196)
==3518==    by 0x402B54: WSUMap::WSUMap() (WSUMap.h:110)
==3518==    by 0x4017CB: __static_initialization_and_destruction_0(int, int)     (main.cpp:8)
==3518==    by 0x4017E0: _GLOBAL__sub_I_map (main.cpp:20)
==3518==    by 0x403DFC: __libc_csu_init (in /home/will/Dev/a.out)
==3518==    by 0x5A2AE3F: (below main) (libc-start.c:203)
==3518== 
==3518== Invalid read of size 4
==3518==    at 0x403240: WSUMap::blockTypeIDAt(unsigned int, unsigned int, unsigned int) const (WSUMap.h:196)
==3518==    by 0x402B54: WSUMap::WSUMap() (WSUMap.h:110)
==3518==    by 0x4017CB: __static_initialization_and_destruction_0(int, int)     (main.cpp:8)
==3518==    by 0x4017E0: _GLOBAL__sub_I_map (main.cpp:20)
==3518==    by 0x403DFC: __libc_csu_init (in /home/will/Dev/a.out)
==3518==    by 0x5A2AE3F: (below main) (libc-start.c:203)
==3518==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==3518== 
==3518== 
==3518== Process terminating with default action of signal 11 (SIGSEGV)
==3518==  Access not within mapped region at address 0x0
==3518==    at 0x403240: WSUMap::blockTypeIDAt(unsigned int, unsigned int, unsigned int) const (WSUMap.h:196)
==3518==    by 0x402B54: WSUMap::WSUMap() (WSUMap.h:110)
==3518==    by 0x4017CB: __static_initialization_and_destruction_0(int, int)     (main.cpp:8)
==3518==    by 0x4017E0: _GLOBAL__sub_I_map (main.cpp:20)
==3518==    by 0x403DFC: __libc_csu_init (in /home/will/Dev/a.out)
==3518==    by 0x5A2AE3F: (below main) (libc-start.c:203)
==3518==  If you believe this happened as a result of a stack
==3518==  overflow in your program's main thread (unlikely but
==3518==  possible), you can try to increase the size of the
==3518==  main thread stack using the --main-stacksize= flag.
==3518==  The main thread stack size used in this run was 8388608.
==3518== 
==3518== HEAP SUMMARY:
==3518==     in use at exit: 3,225,736 bytes in 1,803 blocks
==3518==   total heap usage: 1,816 allocs, 13 frees, 3,279,401 bytes allocated
==3518== 
==3518== 122,880 bytes in 120 blocks are definitely lost in loss record 9 of 13
==3518==    at 0x4C28147: operator new[](unsigned long) (vg_replace_malloc.c:348)
==3518==    by 0x402E7B: WSUMap::blockTypeIDAt(unsigned int, unsigned int, unsigned int) const (WSUMap.h:162)
==3518==    by 0x402B54: WSUMap::WSUMap() (WSUMap.h:110)
==3518==    by 0x4017CB: __static_initialization_and_destruction_0(int, int)     (main.cpp:8)
==3518==    by 0x4017E0: _GLOBAL__sub_I_map (main.cpp:20)
==3518==    by 0x403DFC: __libc_csu_init (in /home/will/Dev/a.out)
==3518==    by 0x5A2AE3F: (below main) (libc-start.c:203)
==3518== 
==3518== LEAK SUMMARY:
==3518==    definitely lost: 122,880 bytes in 120 blocks
==3518==    indirectly lost: 0 bytes in 0 blocks
==3518==      possibly lost: 0 bytes in 0 blocks
==3518==    still reachable: 3,102,856 bytes in 1,683 blocks
==3518==         suppressed: 0 bytes in 0 blocks
==3518== Reachable blocks (those to which a pointer was found) are not shown.
==3518== To see them, rerun with: --leak-check=full --show-reachable=yes
==3518== 
==3518== For counts of detected and suppressed errors, rerun with: -v
==3518== Use --track-origins=yes to see where uninitialised values come from
==3518== ERROR SUMMARY: 1144833 errors from 7 contexts (suppressed: 4 from 4)
Segmentation fault

以下是变量...

size_t i, j, n, m, chunk_size, pixel_size, scale;
i = j = n = m = 0;
chunk_size = 256;
pixel_size = 4;
scale = chunk_size / pixel_size;
float delta, d;

这是数组声明...

for (i = 0; i < pixel_size; ++i) {
    for (j = 0; j < pixel_size; ++j) {
        (i == 0) ? n = i : n = (i * scale) - 1;
        (j == 0) ? m = j : m = (j * scale) - 1;
        a1[n][m] = pixels[i][j];
        a2[n][m] = pixels[i][j];
    }
}
for (i = n = m = d = 0; i < chunk_size; i = m) {
    do {
        std::cout << "m: " << m << " j: " << j << std::endl;
        d = a2[m][j]; <--------------SEGFAULT
        ++m;
    } while (d != 0 && m < chunk_size);

由于您使用的是do ... while()语句,因此只有在第一次运行do while循环后才会检查m < chunk_size。因此,在第二次运行内部for中,第一次运行do ... while循环访问数组边界之外。

您可以将其更改为while(d != 0 && m < chunk_size) { ... }或重写逻辑以确保在m >= chunk_size || j >= chunk_size时不会访问a2[m][j]

在这一行中:

while (n < j + m) {

j+m很容易变得大于块大小。如果您曾经在m大于 chunk_size /2 时绕过第一个循环循环,就会发生这种情况。这将导致写入数组边界之外并导致未定义的行为。

如果chunk_size是256,那么你在这里越界了:

       while (n < j + m) {
            a1[i][n] = a1[i][n - 1] + delta;

n的值变为 256,这超出了范围。

下面是一个示例:http://ideone.com/fAUA8j

每当n变为 256 时,就会打印"You're dead"