dll的struct参数被破坏

时间:2014-09-16 07:13:58

标签: c dll struct

我将用户定义的类型参数从c客户端传递到c dll时遇到问题;我在client和dll中定义了以下结构:

typedef struct sBar{
  double Open;
  double High;
  double Low;
  double Close;
  char NewDateTime[20];
} tBar;

在客户端,我将dll函数声明为

EXPORT int GetPastBars  (int pDebug, char* pDebugPath[], char* pSymbol[], 
    char* pCurrentTime[], int pTotalBars, char* pTimeFrame[], int pIsFilled, 
    char* pOutputType[],    tBar pPastBars[MAX_HISTORY_DEPTH], 
    tBar pFutureBar[PREDICTION_LENGTH]);

同样,在dll源代码中,该函数声明为:

EXPORT int __stdcall GetPastBars(   int pDebug, char* pDebugPath[], char* pSymbol[], 
    char* pCurrentTime, int pTotalBars, char* pTimeFrame[], int pIsFilled, 
    char* pOutputType[], tBar pPastBar[MAX_HISTORY_DEPTH], 
    tBar pFutureBar[MAX_PREDICTION_LENGTH]){

我可以看到pPastBarpFutureBar在dll代码结束之前正确填充;但是,当控件返回到exe时,pPastBar[]的前n个元素归零,n是MAX_PREDICTION_LENGTH(在dll中定义)和PREDICTION_LENGTH之间的差异(在exe)。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

正如评论中指出的那样,双方都没有使用相同的调用约定。你显然需要解决这个问题。

另一个问题是你可能会超越缓冲区。这至少部分是由函数声明中明显的混淆引起的。在编译DLL时,将参数pFutureBar定义为具有一个长度,但在声明中对可执行文件使用不同的长度。

<强> DLL

tBar pFutureBar[MAX_PREDICTION_LENGTH]

<强>可执行

tBar pFutureBar[PREDICTION_LENGTH]

编译器并不关心您在此处指定的数组的长度,只是将指针传递给第一个元素。所以真正重要的是DLL不能访问超出您传递的实际数组的长度。

虽然您没有显示代码,但似乎您可能将数组传递给太短的pFutureBar参数。所以DLL写的超出了它的结尾。很可能你传递了一个长度为PREDICTION_LENGTH的数组,而DLL写了MAX_PREDICTION_LENGTH个元素。假设MAX_PREDICTION_LENGTH大于PREDICTION_LENGTH,那么您将获得经典的缓冲区溢出条件。

您需要做的是将签名更改为

int __stdcall GetPastBars(..., 
    size_t nPastBar, tBar pPastBar[], 
    size_t nFutureBar, tBar pFutureBar[]
);

新参数允许调用者说出它提供的数组有多大。这反过来使被调用者DLL能够避免写入当前正在发生的缓冲区末尾。

通过在DLL中使用相同的头文件以及调用它的代码,您可以使您的生活变得更加轻松。有许多教程和示例可用于说明如何执行此操作。我重复这些是没有意义的。