C memcpy 在 Linux 和 Windows 上的行为不同

标签 c linux windows memory gcc

好的,首先描述一下我的问题。我有一个示例程序,只有一个文件。唯一包含的 header 是标准库的一部分。为了训练和测试,我编写了自己的 malloc 包装器,它会自动将 0 写入整个存储 block 。在我的上网本上(Debian + Gnome 桌面,原始 gcc 调用如下:gcc memstest.c -o memstest)它运行没有问题。对任何其他数据然后 0 的检查是成功的,即使由于基准测试我删除了对存储的每个部分的整个迭代检查。当在 Windows 上使用 Code::Blocks 作为 IDE 和配置的 GNU gcc 编译器尝试此操作时,它告诉我分配的存储空间中有数据(大多数情况下值为 -60)。正如所见,我主要只使用无符号值,因此在将它写入数据 block 时,这个值不可能是我的失败。我猜这是 memcpy 函数,因为它是唯一接触此数据 block 的例程。如果我错了,我会更改主题标题。

这是我的示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iso646.h>
#include <time.h>

void *Smalloc_dyn( unsigned int n_bytes );

int main( void )
{
    time_t start_t, end_t;
    double difference;
    unsigned int index = 0;
    start_t = time( NULL );
    for( index = 0; index < 10000000; index++ )
    {
        char *test = Smalloc_dyn( 65536 );
        if( *test != 0 )
        {
            printf( "Found data without 0 overwriting...\n" );
            return 0;
        }
        free( test );
    }
    end_t = time( NULL );
    difference = difftime( end_t, start_t );
    printf( "Smalloc_dyn took %.1fs\n", difference );
    start_t = time( NULL );
    for( index = 0; index < 10000000; index++ )
    {
        char *test = calloc( ( 65535 / sizeof( (long) 0 ) ), ( 65536 / ( 65535 / sizeof( (long) 0 ) ) ) );
        if( *test != 0 )
        {
            printf( "Found data without 0 overwrting...(2)\n" );
            return 0;
        }
        free( test );
    }
    end_t = time( NULL );
    difference = difftime( end_t, start_t );
    printf( "calloc took %.1fs\n", difference );
    return 0;
}

void *Smalloc_dyn( unsigned int n_bytes )
{
    /*
    This fusion of malloc and a modified memset
    is way faster than calling malloc() and
    after that memset( *dst, 0, len(dst) ).
    We are defining 0 as a long and will
    therefore copy ( for example ) 8 Bytes
    instead of a per-byte copying.
    With a memory need of 1024, we only
    have 128 steps instead of 1024.
    */
    if( 0 == n_bytes )
    {
        return NULL;
    }
    long unsigned int chr = 0;
    unsigned int steps = sizeof( chr ) / n_bytes;
    unsigned int asteps = n_bytes % sizeof( chr );
    unsigned int index = 0;
    char *mem_ptr = malloc( n_bytes );
    if( NULL == mem_ptr )
    {
        return mem_ptr;
    }
    char *write_ptr = mem_ptr;
    for( index = 0; index < steps; index++ )
    {
        memcpy( write_ptr, &chr, sizeof( chr ) );
        write_ptr = write_ptr + sizeof( chr );
    }
    for( index = 0; index < asteps; index++ )
    {
        memcpy( write_ptr, &chr, 1 );
        write_ptr = write_ptr + 1;
    }
    return mem_ptr;
}

编辑:更正代码

最佳答案

为什么steps的值被评估为

unsigned int steps = sizeof( chr ) / n_bytes;

不像

unsigned int steps = n_bytes / sizeof( chr );

?

这看起来像是问题的潜在来源,因为大多数已分配的 block 将由于此错误而未初始化。在“大多数”情况下,steps 将最终为零(例如在您的测试用例中,nbytes65536)。未初始化的数据很容易在平台之间“表现”不同。

关于C memcpy 在 Linux 和 Windows 上的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20436774/

相关文章:

c - 从/proc/<pid>/status 获取 pid 和其他进程信息

c - 使用 PCRS 进行替换的工作示例

c - 这个二叉树算法的条件语句是如何工作的?

C 多结构体只有一个节点

Windows下C程序访问总线上的内容

ruby - 如何使用 system() 杀死已生成子进程的进程?

windows - OSX 上的 scp 不允​​许用户名中有空格?

C 程序 - 如何获取 strtok() 中的第二次出现?

linux - 如何在 *nix 中登录时运行脚本?

java - 如何获取环境变量的值?