MFC读取excel文件程序,在release模式下正常读取,但在debug模式编译没问题,运行就关闭,求高手!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC读取excel文件程序,在release模式下正常读取,但在debug模式编译没问题,运行就关闭,求高手!相关的知识,希望对你有一定的参考价值。

这是错误现象

我的系统是win7 64位,vc++6.0。
程序很简单,就是打开一个EXCEL文件,
编译无错无警告,就是生产EXE后点击打开就出现上面的错误。
于是把生产的exe考到我的xp虚拟机内运行是能够打开文件的,我又回到win7换为Release模式也可以正常打开文件。
用断点调试发现objApp.CreateDispatch("Excel.Application")运行这个就内存泄露,

下面是xp虚拟机内运行效果

下面是用 Release模式运行效果

好奇怪啊,不用Debug后面的调试没法进行,加之在下本为业余,所以请教高手帮忙了。
打开按钮的代码如下:
void CTestDlg::OnOpen()

_Application objApp;
Workbooks objBooks;
COleVariant VOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if(!objApp.CreateDispatch("Excel.Application")) //错误在这里产生

AfxMessageBox("无法启动Excel程序,请正确安装!"); return;

objApp.m_bAutoRelease = TRUE;
objApp.SetVisible(TRUE);
objApp.SetUserControl(TRUE);
LPDISPATCH pWkBooks = objApp.GetWorkbooks();
objBooks.AttachDispatch(pWkBooks,TRUE);
char CurrentProgramPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH,CurrentProgramPath);
CString ExcelFilePathName = CurrentProgramPath;
ExcelFilePathName += \\Data.xls;
objBooks.Open(ExcelFilePathName, VOptional, _variant_t(true), VOptional, VOptional, VOptional, VOptional, VOptional,VOptional, VOptional, VOptional, VOptional, VOptional,VOptional,VOptional);

参考技术A 你用右键 以管理员权限运行 启动vc6再调试试试。追问

刚刚试了,还是不行啊!

追答

那你直接在生成的 exe 上右键 以管理员权限运行 试试呢。

追问

试了,还是不行。刚刚我在xp虚拟机上装了VC,把工程全部复制过去,结果在Debug和Release模式下一切OK,这个win7用起来还真头大啊。

追答

一般都是权限问题导致的,因为你是动态创建对象,win7对这个要求权限控制的比较严格。
其实操作xls还有一种办法就似乎把xls看做是数据库,用 ado 来连接读写。这个应该就没你说的的问题了。好用的ado库可以参见:www.vckbase.com/index.php/wv/469.html

追问

这就是之前用ADO操作的结果,数据库不对,也装不了,没办法才改成现在的方式,至少一半是成功的。

追答

sql语句中表名要加中括号和$,类似这样 [exceldemo$]

本回答被提问者采纳
参考技术B try
if(!objApp.CreateDispatch("Excel.Application")) //错误在这里产生

AfxMessageBox("无法启动Excel程序,请正确安装!");
return;


catch(...)

AfxMessageBox("启动Excel程序出了点问题!");


另外,检查你要打开的excel文件是不是已经打开?还有,这类程序如果你打开了某个excel文件在程序中没有关闭,那么这个excel文件就会一直是打开的,很麻烦。程序意外中断excel文件也不会关闭,最糟糕的情况只有重启。
参考技术C CoInitialize(NULL);
if(!objApp.CreateDispatch("Excel.Application")) //错误在这里产生

AfxMessageBox("无法启动Excel程序,请正确安装!");
return;

...
退出后
CoUninitialize();

mfc 中的 DLL 函数出错

【中文标题】mfc 中的 DLL 函数出错【英文标题】:Error with DLL functions in mfc 【发布时间】:2015-01-02 06:23:42 【问题描述】:

我做了一个小应用程序,我在应用程序类的 Init 实例中加载了一个 DLL。下面提到的代码运行正常,但在发布模式下它正在崩溃。我使用 Visual Studio,DLL 位于应用程序的 Debug 和 Release 文件夹中。

typedef char BufType[4095];
typedef int (*QuickLicenseRT)(BufType);

BufType             Buf;
QuickLicenseRT      pQuickLicense;
HINSTANCE           QL_Lib; 
char*               Message;
int                 i, BufSize;


BOOL CDemo::InitInstance()


INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);

InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();

QL_Lib = LoadLibrary(_T("QuickLicenseRuntime.dll"));
pQuickLicense = (QuickLicenseRT)GetProcAddress(QL_Lib, "QuickLicenseRT");

Message = "ABC";
BufSize = strlen(Message);

for(i=0; i<BufSize; i++)
    Buf[i]= Message[i];

Buf[BufSize] = 0;

MessageBox(NULL, _T("before pQuickLicense (Buf)"), _T("Message"), MB_OK);
(pQuickLicense)(Buf); // here it is crashing
MessageBox(NULL, _T("after pQuickLicense (Buf)"), _T("Message"), MB_OK);
ResponseMessage = Buf;

return TRUE;

我在一些语句之后放置了一些消息框。我注意到在 (pQuickLicense)(Buf) 处,它正在崩溃。加载 QuickLicenseRuntime.dll 后,我得到了函数的地址。我不明白哪里错了。

谢谢

【问题讨论】:

总是检查你的LoadLibrary()GetProcAddress()调用的结果——如果它们不是NULL,那么崩溃是在QuickLicenseRT()逻辑(在DLL中),你可能需要构建一些可选的诊断日志以查看崩溃的位置;调试版本和发布版本之间的主要区别之一是指针初始化... 【参考方案1】:

Buf[BufSize] = 0; 已经写出 Buf 区域,理论上会损坏 pQuickLicense —— 实际上它不应该因为填充而造成伤害。 Buf[BufSize-1] = '\0'; 会更合适。

您还可以修改 typedef int (*QuickLicenseRT)(BufType); 以定义调用约定,即 __cdecl 或 FAR PASCAL。使用错误的调用约定可能会损坏您的数据内存。

一般来说,您的编程风格可能会受益于考虑一些有关 C++ 的基本知识,即 Kerningham 和 Ritchie “用 C 编程”。

【讨论】:

鉴于代码逻辑,Buf[BufSize-1]='\0' 将错误地截断字符串。不管怎样,由于BufSize 是从不相关的数据推导出来的,因此使用BufSizeBufSize-1 作为索引同样是错误的。动态大小的数组,如std::vector 将解决所有问题。然而,缺少的调用约定将是崩溃的主要候选者。函数指针类型应该可以通过库附带的头文件获得。 @Girish:您使用 strlen 而不是 sizeof 编辑了问题中的代码,让我困惑了一分钟。新代码Message = "ABC"; BufSize = strlen(Message); Buf[BufSize] = 0; 只是在它已经存在的地方写入一个 '\0' 字符,因为strlen() 只是对字符进行计数,直到找到一个空字符。如果你真的需要初始化缓冲区,try Buf[0] = 0 or memset(Buf, 0, sizeof(Buf));。如果只想复制字符串,单行strcpy(Buf, Message);就足够了。 这是不正确的。复制字符的循环具有i&lt;BufSize 的终止条件,实质上是在零终止符之前 停止。因此Buf[BufSize]=0 是强制性的。显然,strcpy 更易于使用,因为它已经处理了零终止符。不过,它也无法避免缓冲区溢出。 @IInspectable:假设在 Buf[3] 处为空字符,您错过了从 strlen(Buf) 派生的 BufSize (3)。 我很清楚 source 字符串有一个零终止符。但是,缓冲区副本没有,Buf[BufSize]=0 是强制性的。 Buf 是一个本地对象,因此不是零初始化的。这不是具有静态存储持续时间的对象(将被零初始化)。编辑:我假设 Buf 是一个本地对象。它不是(无论出于何种原因),也不需要Buf[BufSize]=0

以上是关于MFC读取excel文件程序,在release模式下正常读取,但在debug模式编译没问题,运行就关闭,求高手!的主要内容,如果未能解决你的问题,请参考以下文章

MFC中怎么读取Excel文件里的每个单元格内容

如何用MFC打印指定excel

MFC编写的程序,release时出错,希望高手能够指点!!!

VC/MFC动态库Debug版本下正常,Release版本下错误

VS2013生成Release版本MFC程序在其他机器上运行

MFC库已定义的问题