2011-06-09 68 views
0

我正在研究一些C++代码,并在下面描述的函数中遇到一些问题。我之前并没有使用过多的C++,至少不是很久以前,所以我在很大程度上尝试学习。 win32api对混淆因素没有多大帮助...使用'new'在C++中动态分配内存?

该函数被成功调用两次,之后在应用程序中调用该函数时在稍后调用失败时失败。

PTSTR getDomainFromDN(PTSTR dnPtstr) { 

size_t nDn=wcslen(dnPtstr); 
size_t *pnNumCharConverted = new size_t; 

wchar_t *szTemp = new wchar_t[10];   // for debugging purposes 
_itow_s((int)nDn,szTemp,10,10);    // for debugging purposes 

AddToMessageLog(EVENTLOG_ERROR_TYPE,szTemp);  // for debugging purposes (displays an integer value before failing) 
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker A")); // for debugging purposes 
char *dn = new char[nDn]; 
    // !!!!!!!!!!!! all goes wrong here, doesn't get to next line, nDn does have a value when it fails (61) 
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker B")); // for debugging purposes 

wcstombs_s(pnNumCharConverted,dn,nDn+1,dnPtstr,nDn+1); 

...more code here... 

delete[] dn; 
delete pnNumCharConverted; 

return result 
} 

起初我认为这是一个内存分配的问题或东西,因为它失败就行char *dn = new char[nDn];,表示为“标记A”的最后一个标记。我用指针delete[]进一步无效。我知道nDn是一个值,因为我用_itow_s打印出来的消息日志进行调试。我也知道dnPtrstr是一个PTSTR。

我尝试使用malloc以及free()在旧的C风格,但这并没有改善的东西。

+0

一旦你开始摆弄这样的指针,这很棘手 – 2011-06-09 05:19:11

+7

'size_t * pnNumCharConverted = new size_t;'哦我的。 – 2011-06-09 05:20:23

+3

你正在使用太多'new'。 – Nawaz 2011-06-09 05:23:21

回答

2

我尝试过清理你的代码。 C++的一大窍门是在可避免的情况下不能明确地使用内存管理。使用矢量而不是原始数组。字符串而不是char指针。

并且不要不必要地动态分配对象。把它们放在堆栈上,它们被自动释放。

和其他语言一样,初始化变量

PTSTR getDomainFromDN(PTSTR dnPtstr) { 
    std::wstring someUnknownString = dnPtstr; 

    size_t numCharConverted = 0; 

    std::wstring temp; // for debugging purposes 
    std::ostringstream sstr; 
    sstr << temp; 
    AddToMessageLog(EVENTLOG_ERROR_TYPE,sstr.str().c_str());  // for debugging purposes (displays an integer value before failing) 

    AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker A")); // for debugging purposes 
    std::vector<char> dn(someUnknownString.size()); 

    AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker B")); // for debugging purposes 

    wcstombs_s(&numCharConverted, &dn[0], dn.size(), someUnknownString.c_str(), dn.size()); 

    ...more code here... 

    return result 
} 

这可能没有解决您的问题,但它已消除了大量的潜在错误。 鉴于我无法从您提供的代码中重现您的问题,这真的是我能做的最好的。

现在,如果您能够使用理智的名称而不是dnPtstrdn,它可能实际上几乎是可读的。 ;)

+0

“和其他语言一样,初始化变量。”每种语言最近都没有开发出来?:) – GManNickG 2011-06-09 06:30:23

+1

@GMan回到我的日子,我们甚至没有变数!我们只有登记册,我们很高兴有他们! – Kongress 2011-06-09 13:49:04

1

我觉得你的问题是这一行:

wcstombs_s(pnNumCharConverted,dn,nDn+1,dnPtstr,nDn+1);

,因为你是在告诉wcstombs_s高达NDN + 1个字符复制到DN是仅长NDN字符。

尝试改变行:

wcstombs_s(pnNumCharConverted,dn,nDn,dnPtstr,nDn);

或许更好,但:

wcstombs_s(pnNumCharConverted,dn,nDn,dnPtstr,_TRUNCATE);

林不知道你是怎么调试这个或AddToMessageLog是如何实现的,但如果你只是检查日志以跟踪代码,并且AddToMessageLog正在缓冲日志记录,则可能在刷新缓冲区之前发生错误。

+0

是的,我认为我这样做是因为我认为它占字符串末尾的空终止符。尽管代码不会在那里失效,但它在标记A和B之间失败,指向一行'char * dn = new char [nDn];'。我把这个功能当作自己的小程序来使用,它似乎在那里工作得很好。它在前两次在这个应用程序中运行良好,然后在被调用时出错。刚刚尝试了你所说的,它不起作用,但无论如何感谢 – Grub 2011-06-09 05:56:32

+0

@ user723459你可能需要发布生活在“...更多代码在这里......”的代码,也可能有助于查看你在哪里调用这个函数,以及创建dnPtstr的位置以及您对函数结果所做的操作。 – Vusak 2011-06-09 06:05:28

+0

@ user723459超出分配块(通常)的末尾写入不会导致程序立即失败,但它经常会损坏空闲空间舞台,这会在未来某个'new'或'delete'中导致问题。 – 2011-06-09 07:28:08

0

如果您确定“char * dn = new char [nDn];”失败,TRY “set_new_handler” - >http://msdn.microsoft.com/en-us/library/5fath9te(VS.80).aspx

在一个侧面说明,几件事情:

  1. 非常第一操作 “为size_t NDN = wcslen(dnPtstr);”并非100%正确。 假设dnPtstr为unicode,您正在对dnPtstr执行wcslen。但是,情况并非如此,因为根据是否定义了UNICODE,它可能是PWSTR或PSTR。所以,使用_tcslen()。如果你花一些时间来理解UNICODE,非UNICODE的东西,它会更好,因为它们会在Windows C++开发中帮助你很多。
  2. 为什么你使用这么多“新”,如果你只在这个函数中使用这些变量(我假设它)。 首选堆栈的局部变量unles你有一个明确的要求。
+0

我会研究这个,谢谢。有没有人有任何关于一本好C++书的建议,这会让我对所有这些都感兴趣,因为我觉得我需要得到一些基础知识。 ta – Grub 2011-06-09 07:02:45

+0

我将如何重做行'char * dn = new char [nDn];'而不使用'new'? – Grub 2011-06-09 07:04:55

+0

char dn [MAX_SIZE] = {0}; //将MAX_SIZE定义为可以容纳Dn的东西。事实上,由于您使用WindowsAPI,最好使用TCHAR dn [MAX_SIZE] = {0}; – bayCoder 2011-06-09 07:12:04