通过指针值将数据传递给 dll
Posted
技术标签:
【中文标题】通过指针值将数据传递给 dll【英文标题】:Pass data to dll via pointer value 【发布时间】:2016-06-16 11:19:58 【问题描述】:将指针的值(即变量所在的地址)作为整数传递给由同一个主应用程序加载的另一个库,然后创建指向该地址的指针并获取值是否安全?
例如:
#define __STDC_FORMAT_MACROS
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
struct Book
char title[50];
char subject[100];
int book_id;
;
void
DescribeBook(char *label, struct Book *someBook)
printf("\n%s\n", label);
printf("Book title : %s\n", someBook->title);
printf("Book subject : %s\n", someBook->subject);
printf("Book book_id : %d\n", someBook->book_id);
void mem_wipe(uint8_t *ptr, uint64_t len)
while(len--)
*(ptr++) = 0;
void
SomewhereElse(char *addressAsString)
struct Book *myBook;
//PRETEND THIS IS IN A DLL SOMEWHERE ELSE!!!
uint64_t idataptr;
sscanf(addressAsString, "%" PRIu64, &idataptr);
mem_wipe((uint8_t *)addressAsString, strlen(addressAsString));
free(addressAsString);
myBook = (struct Book *)idataptr;
DescribeBook("AFTER", myBook);
printf("Data Address (int): %"PRIu64"\n", idataptr);
printf("Data Address (string): %s\n", addressAsString);
strcpy(myBook->title, "Foo");
strcpy(myBook->subject, "Bar");
myBook->book_id = 7654321;
int
main(void)
struct Book myBook;
uint8_t *dataptr;
char *addressAsString;
strcpy(myBook.title, "Hello");
strcpy(myBook.subject, "World");
myBook.book_id = 1234567;
DescribeBook("BEFORE", &myBook);
printf("Data Address (int): %"PRIu64"\n", (uint64_t)&myBook);
dataptr = (uint8_t *) & myBook;
asprintf(&addressAsString, "%" PRIu64, (uint64_t) dataptr);
if (addressAsString == NULL)
fprintf(stderr, "Error in asprintf\n");
return 1;
printf("Data Address (string): %s\n", addressAsString);
SomewhereElse(addressAsString);
DescribeBook("FINAL (modified)", &myBook);
printf("Data Address (string after wipe): %s\n", addressAsString);
return 0;
请注意,它是统一的,可以运行,但假装 SomewhereElse() 实际上是在一个完全独立的 dll 中,并且 addressAsString 是通过环境设置或其他方式传递的
具体来说-我的问题是“地址是地址还是地址”,或者当内存越过该 dll 屏障时,内存映射方式是否发生了变化,例如 123 != 123("virtual memory " 和 "paging" 是我认为的相关术语,虽然我不太理解)
(实际用例是通过qt->vlc-qt或qmlvlc(c++)传递给libvlc(gnu99 c),通过自定义过滤器设置发送指针值)
作为后续 - 让我们进一步假设我们希望在某个时候以安全的方式擦除内存,并通过优化防止它可能被破坏。是否可以将这样的指针声明为 volatile(我仍然不是 100% 清楚它是如何工作的 - 但搜索安全擦除的示例代码导致了这种情况)?
【问题讨论】:
这是 C 还是 C++?它们之间的转换规则不同。 令人着迷,我不知道...也许您可以将其写为更大答案的一部分?在我的实际用例中,核心应用程序是 c++ (qt),而目标 dll 是 c (gnu99) 暂时不考虑泄漏由asprintf
分配的内存这一事实,这应该可行。想做这件事很奇怪,但我看不出它有什么不奏效的原因。
为什么dll不接受void*
,为什么一定要使用整数类型?你控制那个 dll 的 API 吗?
我不知道如何直接传递一个指针,这个 dll 在我的主应用程序的管道中很远的地方被调用,充其量我可以设置它读取的环境变量,不能直接调用它的函数
【参考方案1】:
您不能将指针作为int
传递,因为您不知道int
是否大到足以容纳指针。您也不应该使用像 int64_t
这样显式大小的整数,因为它们会混淆您的意图。要将指针作为整数传递,您应该使用intptr_t
或uintptr_t
。这些类型是专门提供的,以清楚地表达您的意图并确保(void*)
适合它们。
要安全擦除内存,您必须使用适当的 API。在 Windows 上,这将是 SecureZeroMemory
,在最近的 Unices 上,它是 memset_s
。它不关心它得到什么样的指针,只要它是一个指向数据的指针。
【讨论】:
谢谢!我会把原始代码留在那里,这样你的评论才有意义,而不是修复它。虽然我确实添加了一个“memwipe”,希望它可以工作......虽然保持在主轨道上,但我已经加粗并添加了一个澄清问题。 @davidkomer 您没有理由在 Windows 或带有memset_s
的平台上实现memwipe
。该功能的存在暗示您可能没有足够的知识来正确实施它。如果你这样做了,你会意识到你应该在 Windows 上使用 SecureZeroMemory
而不是在其他地方使用 memset_s
,如果平台不提供它,则回退到特定于平台的变体。
我认为 memset_s 在 gnu99 中不可用...需要研究一下 ;)以上是关于通过指针值将数据传递给 dll的主要内容,如果未能解决你的问题,请参考以下文章
通过 Segue 将数据传递给新的 ViewController
在使用 Laravel 和 Vue 时,通过 Blade Views 将数据传递给 Vue 与使用 Axios 直接传递给 Vue Components 的优缺点是啥? [关闭]