通过指针值将数据传递给 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_tuintptr_t。这些类型是专门提供的,以清楚地表达您的意图并确保(void*) 适合它们。

要安全擦除内存,您必须使用适当的 API。在 Windows 上,这将是 SecureZeroMemory,在最近的 Unices 上,它是 memset_s。它不关心它得到什么样的指针,只要它是一个指向数据的指针。

【讨论】:

谢谢!我会把原始代码留在那里,这样你的评论才有意义,而不是修复它。虽然我确实添加了一个“memwipe”,希望它可以工作......虽然保持在主轨道上,但我已经加粗并添加了一个澄清问题。 @davidkomer 您没有理由在 Windows 或带有memset_s 的平台上实现memwipe。该功能的存在暗示您可能没有足够的知识来正确实施它。如果你这样做了,你会意识到你应该在 Windows 上使用 SecureZeroMemory 而不是在其他地方使用 memset_s,如果平台不提供它,则回退到特定于平台的变体。 我认为 memset_s 在 gnu99 中不可用...需要研究一下 ;)

以上是关于通过指针值将数据传递给 dll的主要内容,如果未能解决你的问题,请参考以下文章

通过 Segue 将数据传递给新的 ViewController

Primeng - 对话服务将数据传递给对话组件

通过 Redirect 将数据传递给组件

Qt C++ - 如何成功地将数据传递给子进程?

在使用 Laravel 和 Vue 时,通过 Blade Views 将数据传递给 Vue 与使用 Axios 直接传递给 Vue Components 的优缺点是啥? [关闭]

我们可以在它被钩住之前将数据传递给 DLLMain 吗?