C中带有字符的内存访问错误问题*

C中带有字符的内存访问错误问题*,c,C,我可以在我的LinuxMint系统上运行一个c程序,而在另一个Linux系统上,如果我遇到内存访问错误,则不会出现问题 void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len) { EVP_MD_CTX *mdctx; if((mdctx = EVP_MD_CTX_create()) == NULL

我可以在我的LinuxMint系统上运行一个c程序,而在另一个Linux系统上,如果我遇到内存访问错误,则不会出现问题

void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len)
{
    EVP_MD_CTX *mdctx;

    if((mdctx = EVP_MD_CTX_create()) == NULL)
        handleErrors();
    if(1 != EVP_DigestInit_ex(mdctx, EVP_sha1(), NULL))
        handleErrors();
    if(1 != EVP_DigestUpdate(mdctx, message, message_len))
        handleErrors();
    if((*digest = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha1()))) == NULL)
        handleErrors();
    if(1 != EVP_DigestFinal_ex(mdctx, *digest, digest_len))
        handleErrors();

    EVP_MD_CTX_destroy(mdctx);
}

void main ()

{
...
    const unsigned char *message= (const unsigned char*) decryptedtext;
    size_t mlen=x;
    unsigned char *digest;
    unsigned int dlen;
    digest_message(message,mlen,&digest,&dlen);

    // if i printf in a for loop i get this memmory access error 
    for(int i=0;i<dlen;i++)
        printf("%x ",digest[i]);
    }

没有出错

为什么会发生这种情况?我怎样才能改变它


提前感谢

我可以发现以下潜在问题

我可以在Linux Mint上运行c程序而不会出现问题

我认为这只是一个令人高兴的巧合,你没有看到问题

若decryptedtext只是一个指针,那个么使用消息进一步访问它是一个非常糟糕的主意。通常,为了访问它,您应该分配内存

理想情况下,mlen应该与消息的长度相关。如果mlen大于消息的实际长度,则存在缓冲区溢出、内存损坏等问题

如何确保dlen不大于摘要中可用的条目数

为什么要将字符串摘要打印为十六进制数

----------- 这太难看了。decryptedtext不是以null结尾的字符串,因此printf不会只打印4个字符

你可以使用:

unsigned char hasharray[3][20];

xc未初始化。

您使用printf%x,digest[i]有一个未定义的行为

正如中提到的,使用错误的格式说明符会导致未定义的行为。这可能就是为什么程序的行为取决于运行的操作系统,也可能取决于硬件和编译器

由于我没有错误消息,很难知道在您的情况下会发生什么,但是由于%x格式说明符通常与unsigned int一起工作,它应该在内存中读取4字节。因为disgest[i]是一个无符号字符,所以它只写在1字节上,这可能就是为什么会出现内存访问错误

void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len)
{
    EVP_MD_CTX *mdctx;

    if((mdctx = EVP_MD_CTX_create()) == NULL)
        handleErrors();
    if(1 != EVP_DigestInit_ex(mdctx, EVP_sha1(), NULL))
        handleErrors();
    if(1 != EVP_DigestUpdate(mdctx, message, message_len))
        handleErrors();
    if((*digest = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha1()))) == NULL)
        handleErrors();
    if(1 != EVP_DigestFinal_ex(mdctx, *digest, digest_len))
        handleErrors();

    EVP_MD_CTX_destroy(mdctx);
}

void main ()

{
...
    const unsigned char *message= (const unsigned char*) decryptedtext;
    size_t mlen=x;
    unsigned char *digest;
    unsigned int dlen;
    digest_message(message,mlen,&digest,&dlen);

    // if i printf in a for loop i get this memmory access error 
    for(int i=0;i<dlen;i++)
        printf("%x ",digest[i]);
    }

在使用printf之前将unsigned char变量digest[i]转换为unsigned int应该可以解决这个问题


此外,还可以帮助您打印十六进制字符

请复制/粘贴错误消息好吗?这将有助于找出问题所在。此外,请为我们提供可编译和可执行的代码,以便我们能够理解什么是不正常的。我们不需要代码中的机密信息,只需要我们理解所需的信息。当您使用调试器单步执行程序时会发生什么?能够使用调试器单步执行程序只是另一个原因,为什么将所有内容都塞进一行代码中,比如if*digest=unsigned char*OPENSSL\u mallocEVP\u MD\u sizeEVP\u sha1==NULL,这是一个非常糟糕的主意。根据您的代码,您根本无法判断调用EVP_MD_size或EVP_sha1是否失败。我有一个bin文件,我想比较一些东西,以便十六进制有帮助。函数digest_消息给了dlen一个值。OK,但是我假设缓冲区长度超过1个字符。该printf只打印1个十六进制代码。由于传递到变量参数列表的参数会出现默认参数升级,因此右值digetst[i]会隐式地从无符号字符转换为int。因此%x应该可以工作@KamilCuk Good point不知道它。虽然,digetst[i]指的是内存的一部分,所以它不应该是右值,而应该是左值,我错了吗?这个事实有可能改变什么吗?我是说。。。是否可以隐式地对左值进行类型转换?C在左值和右值之间并没有任何区别。左值只是一个可以赋值的表达式。rvalue仅表示表达式的值。在C++中,发生了一种叫做LValuto RValf转换和其他魔法的东西,在C中它或多或少没有意义。在C语言中,右值更像是行话。摘要[i]是一个左值,当然是*运算符引起的。我的意思是说rvalue只表示digest[I]表达式的值。C中唯一使用右值术语的地方是only。
size_t mlen=x;
unsigned int dlen;
printf("%x ",digest[i]);
if(decryptedtext[0]==0x25 &&   //%
    decryptedtext[1]==0x50 &&  //P
    decryptedtext[2]==0x44 &&  //D
    decryptedtext[3]==0x46)    //F
{ printf("%s",decryptedtext);
  break;
}
int x;
f = fopen("test.pdf", "w+b");
if(f == NULL) {
printf("Datei konnte nicht geoeffnet werden.\n");
}else {

while(x<decryptedtext_len)  {
    putc(decryptedtext[x],f);
    x++;
}
unsigned char hasharrayone[20];
unsigned char hasharraytwo[20];
unsigned char hasharraythree[20];
unsigned char hasharray[3][20];
int xc;
file = fopen("sxxxxx-dest-cipher.bin", "w+b");
if(file == NULL) {
printf("Datei konnte nicht geoeffnet werden.\n");
}else {
while(xc<cpl)  {
    putc(cfbciphertext[xc],file);
    xc++;
}