【问题标题】:Copy Function Pointer to Block of Memory in C将函数指针复制到 C 中的内存块
【发布时间】:2020-10-04 16:30:56
【问题描述】:

我正在使用 pthreads API 实现一个线程库。我需要做的一件事是分配一个大小为 32767 字节的堆栈,然后将指向 pthread_exit 的函数指针放在堆栈的顶部,并将堆栈指针递减到该函数指针的下方。

我想出的代码如下:

    void *stackPointer = malloc(32767);
    stackPointer += 32767;
    stackPointer -= sizeof(&pthread_exit);
    stackPointer = memcpy(stackPointer, pthread_exit, sizeof(&pthread_exit));

据我所知,通过以这种方式使用 memcpy 函数,函数指针未正确放置在内存中。还有其他方法我应该解决这个问题(或我应该使用的功能)吗?

编辑: 修复代码从一开始就在顶部有堆栈指针

【问题讨论】:

  • 大小奇数。我认为你需要重新考虑它。你需要了解堆栈是如何工作的。回答你的问题记忆是 100% 没问题的。
  • 这在很多方面都是错误的。首先,您增加了sizeof(void (*stackPointer)(void)) squared 字节。其次,正如您所说,堆栈在您的架构上向下增长,因此您应该从 top 开始并递减,第三,32767 看起来指针很奇怪,第四,你不能修改 malloc 返回的指针,否则你将如何释放内存,第四,你确定堆栈指针位置即使在那时也是正确的......
  • memcpy 复制指向的数据,而不是指针本身,但我认为您真正想要编写的是后者。
  • 您确定要堆栈指针指向 below 顶部元素,而不是 at 吗?如果是这样,那么下面有多少字节,1?对于向下增长的堆栈,我的第一个猜测是堆栈指针将指向顶部元素,因此当您想要压入一个值时,您将指针递减该值的大小以找到正确的地址(并且那么写入值后就不需要再调整了。

标签: c stack pthreads posix function-pointers


【解决方案1】:

提供的代码有很多可疑之处。其中有

  • 使用void * 类型的指针进行指针运算是不合规的;
  • 您似乎正在丢弃指向动态分配块的唯一指针,这使得稍后解除分配块变得很棘手(如果可能的话);和
  • 根据您打算如何使用它,您可能无法确保在堆栈上推送的值正确对齐。

但是这些都比较小:一些编译器使用 void-pointer 算术执行您想要的操作,您可能能够重新计算释放块所需的指针,并且对齐对于您的目的而言可能不是问题。

然而,

据我所知,通过这种方式使用 memcpy 函数,函数指针没有正确放置在内存中。

不,绝对不是。 memcpy() 函数将源指针指向的数据复制到目标指针指示的位置。你想自己写指针,这完全是另一回事。

还有其他方法我应该解决这个问题(或我应该使用的功能)吗?

您可以将指针存储在一个变量中,然后从那里复制它:

#define STACK_SIZE 32767

void (*pte)(void *) = pthread_exit;

void *stackLimit = malloc(STACK_SIZE);
void *stackBottom = stackLimit + STACK_SIZE;
void *stackPointer = (char *) stackBottom - sizeof(pte);

memcpy(stackPointer, pte, sizeof(pte));

或者如果未对齐访问不是问题(或者如果堆栈大小略大于或小于 32767 是可以的),那么您可以通过简单的分配更简单地做到这一点:

void *stackLimit = malloc(STACK_SIZE);
void *stackBottom = stackLimit + STACK_SIZE;
typedef void (*pte_type)(void *);

((pte_type) stackBottom)[-1] = pthread_exit;
void *stackPointer = (pte_type) stackBottom - 1;

typedef 是为了清晰和易于阅读。可以不用写等效代码。

请注意,函数类型的表达式,例如pthread_exit,当该函数的声明在范围内时,会自动转换为函数指针。您不需要对它们使用 & 运算符,尽管这样做是无害的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 2013-08-19
    相关资源
    最近更新 更多