0

我正在编写一个 ODBC 数据库类,它包含一个成员函数,用于从给定查询中获取一系列属性和元组。

我在下面的语句中有一行代码导致在调试模式下抛出此运行时错误:

Unhandled exception at <mem loc> in <prog name>: 0xC0000005: Access violation writing location <mem loc>.

这是ERROR指出违规行的代码:

SQLINTEGER length = 0;
vector<vector<string>> data;
this->sReturn = SQLFetch(this->sHandle);

while (this->sReturn == SQL_SUCCESS) {
  vector<string> tuple;

for (int i = 0; i < columnCount; i++) {
  SQLPOINTER value = "";

  switch (info[i].columnType) {
    case 0 : //SQL_UNKNOWN_TYPE
      throw DatabaseAttributeTypeUnknown("The database returned an attribute of an unknown type.");
      break;

    case 1 : //SQL_CHAR
      this->sReturn = SQLGetData(this->sHandle, i + 1, info[i].columnType, value,
        info[i].columnSize*sizeof(SQLCHAR),
ERROR   &length);
        break;

     //Some more cases
  }
}

关于为什么会抛出此错误的任何想法?这是关于 SQLGetData() 的 MSDN 文档,它为length.

感谢您的时间。

4

2 回答 2

1

当编译器将可执行代码映射到源代码中的代码行时,它们通常无法区分被拆分为多行的语句中的行。因此,如果调试器说错误发生在特定行上,它实际上可以在整个语句中的任何位置,所以在某处:

this->sReturn = SQLGetData(this->sHandle, i + 1, info[i].columnType, value,
    info[i].columnSize*sizeof(SQLCHAR),
    &length);

这里唯一不稳定的指针是value指向一个空静态字符串,所以指向一个包含空字节的单字符长数组。此外,根据编译器选项,此数组可以位于只读数据段中。虽然 SQLGetData() 认为它指向的位置至少为info[i].columnSize*sizeof(SQLCHAR)字节大小,并且它将从 SQL 列写入(而不是读取)数据。

我可能会错过其他细节,但我的第一个猜测是这就是导致内存访问冲突的原因。

于 2012-10-31T02:38:42.033 回答
0

In addition to what Frederic said. Are you compiling your code 64 bit? If so you'll find SQLGetData takes a pointer to an SQLLEN for the last argument not an SQLINTEGER:

SQLRETURN  SQL_API SQLGetData(SQLHSTMT StatementHandle,
                              SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
                              SQLPOINTER TargetValue, SQLLEN BufferLength,
                              SQLLEN *StrLen_or_Ind);

An SQLLEN is 8 bytes in 64 bit windows not 4 bytes as SQLINTEGER is.

于 2012-10-31T08:16:01.850 回答