首页 > 解决方案 > memcpy 指向 char 缓冲区的指针

问题描述

我目前正在尝试一些不同的作业系统实现(基于本文)。

我试图解决的问题是将参数传递给“作业函数”。

这是我的Job定义:

#define JOB_DATA_PADDING_SIZE   44

/** A job function is a function that can be worked on by the job manager */
typedef void( *JobFunction )( struct Job*, const void* );

/// <summary>
/// A job is something that represents work to be done by the thread pool.
/// Contains a pointer to it's work function and a counter to how many jobs
/// still need to be completed.
/// </summary>
struct Job
{
    JobFunction Function;                       // 8 byte
    Job* Parent;                                // 8 byte
    std::atomic<int32_t> UnfinishedJobs;        // 4 byte
    char Padding[ JOB_DATA_PADDING_SIZE ];      // 44 bytes, so that this object fills
                                                // a whole x64 cache line
};

如您所见,char Padding为了避免错误共享,需要存在缓冲区。我想使用该缓冲区来简单地存储需要传递给JobFunction用户调用的任何参数的方法。此设置运行良好,但有一个例外:将指针作为参数传递。

当用户去创建工作时,他们在以下位置调用此函数JobManager

Job * JobManager::CreateJob( JobFunction aFunction, void* args, size_t aSize )
{
    assert( aSize >= 0 && aSize < JOB_DATA_PADDING_SIZE );

    Job* job = AllocateJob();
    job->Function = aFunction;
    job->Parent = nullptr;
    job->UnfinishedJobs.store( 1 );

    // Memcpy the args to the jobs padding
    if ( args != nullptr )
    {
        memcpy( job->Padding, args, aSize );
    }

    return job;
}

如您所见,计划是memcpy将用户提供给函数的参数简单地放入Padding. 这适用于结构之类的东西,实际上是任何小于该44字节大小的数据。

我想要做的是一个指向该数组memcpy的给定指针。但是,当我尝试这样做时,我遇到了复制指针处的值并将其复制到缓冲区中的问题。Paddingmemcpy

有没有办法可以memcpy将实际指针放入缓冲区?

我尝试过尝试uint64_tuintptr_t无济于事。

有没有办法做到这一点?我完全错了这应该如何工作?

如果这也有助于提供更多上下文,则整个项目都在GitHub 上。

标签: c++multithreadingjob-scheduling

解决方案


有没有办法可以将实际指针存储到缓冲区中?

当然。Memcpy 不在乎它在复制什么。它所做的只是将字节从源位置复制到目标位置。

假设您想复制一个int值。Memcpy 不知道int值。它只知道位置。因此,您必须将值放入某个内存位置(例如,放入int 变量),然后您可以给 memcpy 一个指向它的指针。

extern void* destination_pointer;
int source = getIntValueFromWherever();          // put the value into the source location
size_t n_bytes = sizeof(source);
memcpy(destination_pointer, &source, n_bytes);   // then give memcpy a pointer to it.

但是你想复制一个指针。好吧,这是同样的交易。您要复制的内容(例如,某个foobar_t*指针)必须存储在某个位置(例如,在变量中)。然后你给 memcpy 指向源和目标位置的指针。

与上面的示例唯一不同的是变量int的数据类型:source

extern void* destination_pointer;
foobar_t* source = getPointerFromWherever();     // put the value into the source location
size_t n_bytes = sizeof(source);
memcpy(destination_pointer, &source, n_bytes);   // then give memcpy a pointer to it.

推荐阅读