覆盖char *指针

时间:2014-08-14 19:44:39

标签: c++ pointers

我有一个供应商应用程序,我相信是使用C或C ++构建的,并且它可以对DLL进行特定调用以允许扩展功能。我正在尝试为该dll编写POC,并且仅使用此作为规范: extern int __stdcall LIQEXIT3_LoadCustomer(const char* name, char* id);

我应该能够传入一个char *名称,然后在id字段中返回相同的char *。不幸的是,这不是正在发生的事情。我要么获得访问冲突,要么一切正常,但调用应用程序不会在ID字段中获取新信息。

我创建了以下DLL和头文件代码: TestDLL.h

#ifdef TestDLL_EXPORTS
#define TestDLL_API __declspec(dllexport)
#else
#define TestDLL_API __declspec(dllimport)
#endif

namespace TestDLL
{
    class TestDLL
    {
    public:
        static int __declspec(dllexport) __stdcall  TestDLL::TestMethod_LoadCustomer(const char* name,  char* id);
    };
}

TestDLL.cpp

// TestDLL.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#include "TestDLL.h"
#include <string>

namespace TestDLL{
    extern "C" int __declspec(dllexport) __stdcall  TestDLL::TestMethod_LoadCustomer(const char* name, char* id)
    {
        std::string test(name); 

        if (test.size() <= 8) {
            id = (char*)malloc(strlen(name)+1);
            strcpy(id, name);           // name contains customer id
        } else {
            id[0] = 0;                  // Customer not found
        }

      return 0;
    }
}

当我对TestMethod_LoadCustomer方法进行简单调用并且我在代码中有id字段的malloc时,一切似乎进展顺利,但我的调用代码没有获得更新的id字段。如果我删除malloc调用,我会收到访问冲突。我认为违规是由于id字段将被放入只读存储器而不能直接覆盖。

如何对此进行编码,以便调用应用程序在id字段中接收字符串的更新值?

这是我放在一起的测试应用程序代码,我希望这个代码名称为&#34; 777777&#34;并将其移动到id字段,以便它可以打印到控制台: RunTest.cpp

// RunTest.cpp : Defines the entry point for the console application.
//
#ifdef TestDLL_EXPORTS
#define TestDLL_API __declspec(dllexport)
#else
#define TestDLL_API __declspec(dllimport)
#endif

#include "stdafx.h"
#include <iostream>
#include "TestDLL.h"

using namespace std;
int _tmain()
{
    char* id= "";
    TestDLL::TestDLL::TestMethod_LoadCustomer("777777", id);
    cout << id << "\n";
    cout <<"This is a Test\n";
    cin >> id;
    return 0;
}

感谢您花时间看看我的问题!

3 个答案:

答案 0 :(得分:1)

您需要将第二个参数类型更改为char *&id;当您在id = ...TestMethod_LoadCustomer进行id时,您只会更改id的本地版本,而不是外部的&变量。

在参数中添加id会使char引用id指针,这意味着来自_tmain的{​​{1}}将通过引用传递,并且你的代码会起作用。

答案 1 :(得分:0)

您正在修改DLL中指针的值。由于指针id未作为对指针char *&id的引用传递,因此对指针值的更改不会反映在TestMethod_LoadCustomer函数的范围之外。我还认为在一个dll中分配内存以跨模块使用是一个坏主意,因为那时你必须确保你的程序和dll都使用相同的C ++运行时编译。更安全的方法是将已分配的缓冲区传递给函数,并让调用程序处理内存管理。

看看here,了解为什么你应该在调用代码中保留资源的所有权。

答案 2 :(得分:0)

您的代码中存在一些问题。 一个小问题是你正在混合C和C ++代码,它可以工作,但可能会混淆理解。 即:您使用std类/对象,但使用c字符串函数(strcpy)和malloc函数。

当您使用 id 参数调用函数时,它会传递指针,指向一个常量值。

:在主函数中,id的值(即它指向的地址)是0x123。 但是,在DLL函数内部为id分配内存,所以现在该函数内的 id 指向不同的地址(即:0x456)

然后,当您的程序返回主函数 id 时仍然指向旧地址,因为函数内部的更改不会反映在外部(因为您更改为其中的位置&#39) ; s指的不是值。)

为了让它按预期工作,您需要确保主要功能 id 中的功能都指向同一个地址,并确保您要更改的位置价值。

为了达到这个目的,你可以使用,即指针指针或指针作为id,然后你可以分配值和复制。

您的代码的丑陋(但功能)版本将是:

namespace TestDLL{
    extern "C" int __declspec(dllexport) __stdcall  TestDLL::TestMethod_LoadCustomer(const char* name, char* id)
    {(char* name, char** id) {
        std::string test(name);

        if (test.size() <= 8) {
            *id = (char*)malloc(strlen(name)+1);
            strcpy(*id, name);           // name contains customer id
        } else {
            id[0] = 0;                  // Customer not found
        }

      return 0;
}

然后你可以调用传递指针的地址:

int _tmain()
{
    char* id= "";
    TestDLL::TestDLL::TestMethod_LoadCustomer("777777", &id);
    cout << id << "\n";
    cout <<"This is a Test\n";
    cin >> id;
    return 0;
}

但我强烈建议您将代码更改为C或C ++,而不是两者,并且不要忘记_tmain拥有id指针,因此当您不需要时需要释放内存了。