C中的malloc()内存损坏

C中的malloc()内存损坏,c,memory,malloc,sha1,memory-corruption,C,Memory,Malloc,Sha1,Memory Corruption,malloc()在下面的代码中给了我一个错误。我用了valgrind,但仍然没有用。我是C语言的初学者,我的队友和我都在尝试实现SHA1算法,但有些东西我们都不理解,而且花了很多时间在这上面。这是函数中有错误的部分- /* * Returns an array of chunks on the heap from the message */ static unsigned char **sha1_chunkify(const unsigned char *message, const u

malloc()在下面的代码中给了我一个错误。我用了valgrind,但仍然没有用。我是C语言的初学者,我的队友和我都在尝试实现SHA1算法,但有些东西我们都不理解,而且花了很多时间在这上面。这是函数中有错误的部分-

/*
 * Returns an array of chunks on the heap from the message
 */

static unsigned char **sha1_chunkify(const unsigned char *message, const uint64_t message_length)
{
    long num_chunks = message_length / 64;    //breaking it down into 64 byte chunks
    printf("%lu %ld\n", message_length, num_chunks);
    unsigned char **chunks = malloc (num_chunks * sizeof(*chunks)); //Error is coming over here

    for (int i = 0; i < num_chunks; i++) {
        chunks[i] = malloc (64 * sizeof(*chunks[i])); //Or sometimes over here.

        for (int j = 0; j < 64; j++) {
            chunks[i][j] = message[64 * i + j];
        }
    }

    return chunks;
}
Valgrind显示了以下内容-

3
mytry.c
==16688== Invalid write of size 1
==16688==    at 0x401EA6: append_zeroes (sha1.c:155)
==16688==    by 0x401F1D: sha1_pad (sha1.c:177)
==16688==    by 0x401FB7: sha1 (sha1.c:200)
==16688==    by 0x400C72: snap_file (snap.c:40)
==16688==    by 0x4012F7: snap (snap.c:143)
==16688==    by 0x401852: snap_all (snap.c:220)
==16688==    by 0x40222E: main (nako.c:24)
==16688==  Address 0x5220720 is 0 bytes after a block of size 1,408 alloc'd
==16688==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16688==    by 0x401F7B: sha1 (sha1.c:195)
==16688==    by 0x400C72: snap_file (snap.c:40)
==16688==    by 0x4012F7: snap (snap.c:143)
==16688==    by 0x401852: snap_all (snap.c:220)
==16688==    by 0x40222E: main (nako.c:24)
==16688== 
==16688== Invalid write of size 1
==16688==    at 0x401E6A: append_msg_len (sha1.c:142)
==16688==    by 0x401F34: sha1_pad (sha1.c:179)
==16688==    by 0x401FB7: sha1 (sha1.c:200)
==16688==    by 0x400C72: snap_file (snap.c:40)
==16688==    by 0x4012F7: snap (snap.c:143)
==16688==    by 0x401852: snap_all (snap.c:220)
==16688==    by 0x40222E: main (nako.c:24)
==16688==  Address 0x5220758 is not stack'd, malloc'd or (recently) free'd
==16688== 
1472 23

valgrind: m_mallocfree.c:277 (mk_plain_bszB): Assertion 'bszB != 0' failed.
valgrind: This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata.  If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away.  Please try that before reporting this as a bug.

==16688==    at 0x38050BAC: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x38050D06: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x3805B36A: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x3805D2D7: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x380216D4: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x380218A2: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x3809DC03: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==16688==    by 0x380AC87C: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)

sched status:
running_tid=1

Thread 1: status = VgTs_Runnable
==16688==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16688==    by 0x401D94: sha1_chunkify (sha1.c:118)
==16688==    by 0x401FCA: sha1 (sha1.c:202)
==16688==    by 0x400C72: snap_file (snap.c:40)
==16688==    by 0x4012F7: snap (snap.c:143)
==16688==    by 0x401852: snap_all (snap.c:220)
==16688==    by 0x40222E: main (nako.c:24)
我已经经历了几个线程,但错误仍然存在。如果以前有人问过,我道歉。我找不到同样的。先谢谢你

下面是函数append_zero和append_msg_len-

/*
 * Pad the message with its length.
 * The input lengths are in bytes, while the padding, in accordance with
 * the SHA1 algorithm, is done in bits.
 */
static inline void append_msg_len(unsigned char *message,
                  uint64_t *message_length,
              uint64_t original_msglen)
{
    int shift = 56;
    while (shift >= 0) {
        /* Add the next 8 bits. */
         message[*message_length] = (8 * original_msglen >> shift) & 0xff;
         shift -= 8;
    *message_length += 1;
    }
}

/*
 * Appends enough zeroes until the message has just enough room for appending
 * the message length, i.e, length 448 mod 512
 */
static inline void append_zeroes(unsigned char *message, uint64_t *message_length)
{
    while (*message_length % 64 != 56) {
        message[*message_length] = (unsigned char) 0x00;
        *message_length += 1;
    }
}
查看此代码:

long num_chunks = message_length / 64;    //breaking it down into 64 byte chunks
例如,如果我们使用
message\u length
=63,
num\u chunks
变为零,这显然是错误的。如果您改为使用:

long num_chunks = (message_length + 63) / 64;    //breaking it down into 64 byte chunks

您将获得正确数量的块,希望您的其余代码表现良好。

valgrind输出非常清楚地表明问题不在您发布的代码中,而是在
append\u zeroes()
中。这一行:
long num\u chunks=message\u length/64
是一个整数除法,因此会导致num_chunks比实际的块数少1,因为任何分数都被截断。发布的代码包含
magic
数字64。使用
magic
数字会使代码更难理解,并且在执行维护时会引起严重的麻烦。强烈建议使用枚举或#define来创建一个有意义的名称,并在整个代码中使用该有意义的名称。@user3629249:不,这行非常好。建议将:
long num_chunks=message_length/64
替换为:
long num_chunks=(message_length+63)/64
如果消息长度不是64的倍数,则这只是一个问题,并且在本代码中,只会导致一些数据丢失,这可能是错误的,但不会导致所询问的错误。此函数中的代码不会写入超出分配空间的末尾。假设
消息长度
不总是64的倍数,我想其他代码(如
附加零
)可以正确计算块并尝试使用未分配的块?但是我们在猜测,没有
append_zero
code。当然这是可能的。在无效写入位置有相当多的堆栈跟踪,问题可能在任何地方。。。
long num_chunks = (message_length + 63) / 64;    //breaking it down into 64 byte chunks