【问题标题】:Getline error MFC vs2012 (msvcp110.dll)Getline 错误 MFC vs2012 (msvcp110.dll)
【发布时间】:2012-11-07 05:06:28
【问题描述】:

我在将 vs2012 中的 std::getline 函数与 MFC 应用程序一起使用时遇到问题。相同的代码在 vs2010 中运行,这就是为什么我确信它不是代码本身的问题。

void AddImage::OnClickedIdbAiRegistration(){
CFileDialog file(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "(*.dat)|*.dat||");
file.DoModal();
UpdateData();
m_ai_file=file.GetPathName();
UpdateData(FALSE);
std::string buf=m_ai_file;
if(filecnt(buf, "Dat")){
    std::ifstream file(buf);
    AfxMessageBox(buf.c_str());
    std::getline(file, buf);//Here is my problem
    AfxMessageBox(buf.c_str());
    file.close();
    }
}

第一个 AfxMessageBox 返回文件路径(正确且有效的 ASCII 文件)。我永远无法到达第二个 AfxMessageBox,因为 getline 产生:

program.exe 中 0x000007FEF7B4AAEE (msvcp110.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0xFFFFFFFFFFFFFFFF。

vs11 将我重定向到 xiosbase 第 443 行

    locale __CLR_OR_THIS_CALL getloc() const
    {   // get locale
    return (*_Ploc);/*THIS IS LINE 443*/
    }

对于项目属性,我使用“在共享 dll 中使用 MFC”和“多线程 DLL”和子系统“Windows”

附加程序代码,包括:

#include <afxwin.h>
#include <afxframewndex.h>
#include <afxcmn.h>
#include <afxdialogex.h>

#include <iostream>
#include <string>
#include <sstream>
#include <regex>
#include <fstream>
#include <time.h>
#include <Windows.h>

usign namespace std;

class AddImage:public CDialog{
        DECLARE_DYNAMIC(AddImage)
    public:
        AddImage(CWnd* pParent = NULL);
        virtual ~AddImage();
        enum {IDD=IDD_ADD_IMAGE};
    protected:
        virtual void DoDataExchange(CDataExchange* pDX);
        DECLARE_MESSAGE_MAP()
    public:
        CString m_ai_file;
    };

AddImage::AddImage(CWnd* pParent):CDialog(AddImage::IDD, pParent){
    m_ai_file=_T("");
    }

AddImage::~AddImage(){
    }



bool filecnt(string path, string type){
    if(filepathcnt(path, type)){
        if(GetFileAttributes(path.c_str())==-1){
            return(FALSE);
            }
        else{
            return(TRUE);
            }
        }
    else{
        return(FALSE);
        }
    }

bool filepathcnt(string path, string type){
    if(type==""){
        tr1::regex regex("[[:print:]]+\\.[[:alnum:]]+");
        if(regex_match(path.begin(), path.end(), regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    else if(type=="-"){
        tr1::regex regex("[[:print:]]+");
        if(regex_match(path.begin(), path.end(), regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    else{
        string upper=type;
        string lower=type;
        transform(upper.begin(), upper.end(), upper.begin(), toupper);
        transform(lower.begin(), lower.end(), lower.begin(), tolower);
        tr1::regex norm_regex("[[:print:]]+\\."+type);
        tr1::regex upper_regex("[[:print:]]+\\."+upper);
        tr1::regex lower_regex("[[:print:]]+\\."+lower);
        if(regex_match(path.begin(), path.end(), upper_regex) || regex_match(path.begin(), path.end(), lower_regex) || regex_match(path.begin(), path.end(), norm_regex)){
            return(TRUE);
            }
        else{
            return(FALSE);
            }
        }
    }

有人知道出了什么问题吗?

【问题讨论】:

  • 您是否清理了项目并进行了完整的重建,包括所有依赖的 dll?
  • 是的,我试过了,但没有解决问题。

标签: c++ mfc visual-studio-2012 getline


【解决方案1】:

我现在已经通过使用 VS10 解决了这个问题。那里的算法没有任何问题。但我认为这不是解决方案!

它可以在同一台 PC 上与 vs10 一起使用,这也告诉我这不是 PC 的问题。

【讨论】:

    【解决方案2】:

    当您打开一个文件对象时,您应该在尝试使用它之前始终确保它是有效的。

    if (file.bad())
        AfxMessageBox("Bad file");
    else
    { // existing code follows
    

    附:在同一个代码块中有两个名为 file 的对象。请不要这样做,即使编译器能够保持正确,它也可能会造成混淆。

    【讨论】:

    • 如果尝试过但我仍然遇到同样的错误。看起来他实际上能够打开它但不能阅读它。
    【解决方案3】:

    首先让我们简化问题:

    只需硬编码路径并在新的控制台项目中运行它:(我添加了更多保护代码)

    
        String buf="the data file path";
        std::ifstream file(buf);
        if(!file.is_open())
            return FALSE;
        while(file.good())
        {
            cout << buf << endl;
            std::getline(file, buf);
            cout << buf << endl;
        }
        file.close();
    

    结果如何?如果问题仍然存在,您可以在第二个 cout

    您还应该按以下方式保护 FileDialog:否则一旦单击“取消”,它将失败。

    
    (dlg.DoModal()==IDOK)
      FilePathName=dlg.GetPathName();
      //....other opertiaon
    } 
    

    【讨论】:

    • consol 程序使用指定的硬编码文件路径。但不是在 MFC 中。
    【解决方案4】:

    也许在之前包含文件路径的字符串中写入行内容不是一个好主意。请尝试以下操作:

    CString csFilePath("C:\\example.txt");
    ifstream infile;
    infile.open(csFilePath);
    
    std::string strLine;
    std::getline(infile, strLine);
    

    顺便问一下,您是否复制并粘贴了您的代码?正如你所写:

    使用命名空间标准;

    而不是使用命名空间标准;

    【讨论】:

    • 如果为文件名添加了一个新的 CString 但它不会改变任何东西。代码是在 vs10 和 vs11 之间复制的,但发布的程序代码包含许多不同的文件,因此 using namespace 行是手写的。
    • 由于ifstream没有返回值,你应该检查stream是否适合i/o操作:if (!infile.good()) return;如果程序此时返回,你必须确保文件是可写的(工具运行时文件是否打开?您有足够的权限吗?)
    • 我在第一个答案中添加了if(file.bad())。该文件未在其他任何地方打开,我有权对其进行编辑(我可以编写和附加内容)。
    • file.bad()!file.good() 不一样 总是使用第二个,因为正如我已经提到的,它会检查流的状态是否适合 i/o 操作。 bad() 只检查是否设置了 badbit。
    • 是的,它适用于 i/o 操作。现在检查 !file.good() 而不是 file.bad()
    【解决方案5】:

    它正在工作,但现在已经不存在了。

    将编译标志(在项目属性 > 配置属性 > C++ > 代码生成 > 运行时库中)从 /MD(多线程 DLL)更改为 /MDd(多线程调试 DLL),用于调试和发布配置。

    这至少应该在 VisualStudio 2012 中工作。

    【讨论】:

    • 你能解释一下为什么这会帮助 OP 解决他们的问题吗?
    • 我不知道 OP 是谁,但这可能会对 B4DBOY 有所帮助,因为他的问题与我所困扰的问题有很大的相似之处,因此得到了解决。
    • “OP”指的是原创海报,所以当我说 OP 时,我指的是 B4DB0Y。
    • 好的。道歉。现在由于这项工作的原因,它确实需要链接器使用 MSVCRTD.lib 而不是 MSVCRT.lib 并将其包含在 .obj 文件中。为什么它在 VS10 中有效而在 VS11 中不再有效,这可能是在 Microsoft VS 更新的奥秘中找到的。
    猜你喜欢
    • 2013-06-18
    • 2013-08-20
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    相关资源
    最近更新 更多