C++ 通过指针值将数据传递给dll

C++ 通过指针值将数据传递给dll,c++,c,qt,libvlc,C++,C,Qt,Libvlc,将指针的值(即变量所在的地址)作为整数传递给同一主应用程序加载的另一个库是否安全,然后该库会创建指向该地址的指针并获取该值 例如: #define __STDC_FORMAT_MACROS #include <stdio.h> #include <inttypes.h> #include <string.h> #include <stdlib.h> struct Book { char title[50]; c

将指针的值(即变量所在的地址)作为整数传递给同一主应用程序加载的另一个库是否安全,然后该库会创建指向该地址的指针并获取该值

例如:

#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;
}
\define\u STDC\u FORMAT\u宏
#包括
#包括
#包括
#包括
结构书{
字符标题[50];
字符主题[100];
国际图书标识;
};
无效的
descripebook(char*标签,struct Book*someBook)
{
printf(“\n%s\n”,标签);
printf(“书名:%s\n”,someBook->title);
printf(“书籍主题:%s\n”,someBook->subject);
printf(“图书id:%d\n”,someBook->Book\u id);
}
无效内存擦除(uint8\u t*ptr,uint64\u t len){
而(len--){
*(ptr++)=0;
}
}
无效的
其他地方(字符*地址字符串)
{
结构书*myBook;
//假装这是在其他地方的DLL中!!!
uint64_t idataptr;
sscanf(地址字符串,“%”PRIu64和idataptr);
mem_wipe((uint8_t*)地址字符串,strlen(地址字符串));
免费(addressAsString);
myBook=(结构书*)idataptr;
描述书(“之后”,myBook);
printf(“数据地址(int):%“PRIu64”\n”,idataptr);
printf(“数据地址(字符串):%s\n”,地址字符串);
strcpy(myBook->标题“Foo”);
strcpy(myBook->subject,“Bar”);
myBook->book_id=7654321;
}
int
主(空)
{
结构书myBook;
uint8_t*dataptr;
字符*地址字符串;
strcpy(myBook.title,“你好”);
strcpy(myBook.subject,“世界”);
myBook.book_id=1234567;
descripebook(“之前”、&myBook);
printf(“数据地址(int):%“PRIu64”\n”(uint64\t)和myBook);
dataptr=(uint8_t*)和myBook;
asprintf(&addressAsString,“%”优先级64,(uint64)数据ptr);
if(addressAsString==NULL){
fprintf(stderr,“asprintf中的错误”);
返回1;
}
printf(“数据地址(字符串):%s\n”,地址字符串);
其他地方(地址字符串);
描述手册(“最终(修改)”,&myBook);
printf(“数据地址(擦除后的字符串):%s\n”,addressAsString);
返回0;
}
请注意,它在那里是统一的,可以运行,但假设somewhere()实际上位于一个完全独立的dll中,并且addressAsString是通过环境设置或其他方式传递的

特别是-我的问题是“地址就是地址就是地址”,还是当内存跨越dll屏障时,内存映射方式发生了变化,例如123!=123(“我认为虚拟内存”和“分页”是相关的术语,尽管我不太理解它们)

(实际用例通过qt->vlcqt或qmlvlc(c++)传递给libvlc(gnu99 c),并通过自定义过滤器设置发送指针值)


接下来,让我们进一步假设,我们希望在某个时刻以安全的方式擦除内存,并通过优化防止内存损坏。这样的指针是否可以声明为易失性的(我仍然不是100%清楚它是如何工作的,但搜索安全擦除的示例代码导致了这种情况)?

您不能将指针作为
int
传递,因为您不知道
int
是否足够大以容纳指针。您也不应该使用显式大小的整数,如
int64\t
,因为它们会混淆您的意图。要将指针作为整数传递,应该使用
intptr\u t
uintpr\u t
。提供这些类型是为了明确表达您的意图,并确保
(void*)
适合它们


要安全地擦除内存,必须使用适当的API。在Windows上,就是在最近的Unice上。它不关心它得到什么样的指针,只要它是指向数据的指针。< /P>是C还是C++?它们之间的转换规则不同。很有趣,我不知道。。。也许你可以把它写下来作为更大答案的一部分?在我的实际用例中,核心应用程序是C++(Qt),而目标DLL是C(GNU99),暂时忽略了您泄漏的内存:<代码> ASPrTFF < /C> >,这应该是可行的。这是一件奇怪的事情,但我看不出它不起作用的任何原因。为什么dll不接受
void*
,为什么必须使用整数类型?你控制那个dll的API吗?我不知道如何直接传递指针,dll是从我的主应用程序调用的,最多我可以设置它读取的环境变量,不能直接调用它的函数谢谢!我将保留原始代码,这样您的注释才有意义,而不是修复它。虽然我添加了一个“memwipe”,希望它能起作用。。。不过,为了保持重点,我加粗并添加了一个澄清问题。@davidkomer您没有理由在Windows或带有
memset\u
的平台上实施
memwipe
。该函数的存在暗示您可能不知道如何正确实现它。如果您这样做了,您就会意识到
SecureZeroMemory
是您应该在Windows和其他地方使用的,如果平台不提供,您可以回退到平台特定的变体。我认为gnu99中没有memset_s。。。需要对此进行调查;)