结构体的c++内存分配

C++ memory allocation for a structure

本文关键字:分配 内存 c++ 结构体      更新时间:2023-10-16

我被赋予了一个任务来创建dll,我需要为结构分配和释放内存。不幸的是,我不知道如何检查代码是否有效。

#pragma once
#include "stdafx.h"
#include "RandomBlockHeader.h"
#include <iostream>
#include <ctime>
using namespace std;
namespace RandBlock {
unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK ** ppRandomBlock) {
    try {
        srand(time(NULL));
        ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK));
        int random = rand() % 129;
        (**ppRandomBlock).ulRandomLen = random;
        (**ppRandomBlock).pRandomData = new unsigned char[random];
        for (int i = 0; i < random; i++) {
            (**ppRandomBlock).pRandomData[i] = (char)(rand() % 256);
        }
        return 0;
    }
    catch (exception& e) {
        return -1;
    }
}
unsigned long FreeRandomBlock(RANDOM_BLOCK * pRandomBlock) {
    try {
        delete pRandomBlock;
        return 0;
    }
    catch (exception& e) {
        return -1;
    }
}
}

谁能指出我哪里可能有错误?这是一个正确的方式来分配内存的两个指针结构?

   ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK));

不好。我想应该是:

    *ppRandomBlock = (RANDOM_BLOCK*)malloc(sizeof(RANDOM_BLOCK));

更好的是,由于您使用的是c++,将函数接口更改为:

unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*&  ppRandomBlock) { ... }

然后,函数将看起来更干净(根本不使用malloc):

unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*& ppRandomBlock) {
   try {
      srand(time(NULL));
      ppRandomBlock = new RANDOM_BLOCK;
      int random = rand() % 129;
      (*ppRandomBlock).ulRandomLen = random;
      (*ppRandomBlock).pRandomData = new unsigned char[random];
      for (int i = 0; i < random; i++) {
         (*ppRandomBlock).pRandomData[i] = (char)(rand() % 256);
      }
      return 0;
   }
   catch (exception& e) {
      return -1;
   }
}

我假设RANDOMBLOCKstruct类型,包含(至少)两个成员- ulRandomLen类型为int(不考虑其名称),pRandomData类型为指向unsigned char的指针。

基于这些假设,代码有以下问题

  • 函数返回类型为unsigned long,返回-1。这(幸运的是)具有良好定义的效果—它返回unsigned long可以表示的最大值。然而,这可能不是调用者所期望的。
  • 每次调用该函数时,代码都会调用srand()。这将——除非程序运行很长时间——重新初始化随机数种子,并导致rand()返回相同的随机值序列。你需要确保srand()在COMPLETE程序中只被调用一次,在rand()的第一次调用之前。
  • 语句ppRandomBlock = (RANDOM_BLOCK**)malloc(sizeof(RANDOM_BLOCK))需要分配sizeof(RANDOMBLOCK *),而不是sizeof(RANDOM_BLOCK)。更好的是,将语句替换为ppRandomBlock = new (RANDOM_BLOCK *),并且不必担心大小问题。
  • 前面的语句的问题(无论是否固定)是,它不分配RANDOMBLOCK,并留下*ppRandomBlock未初始化。这导致所有通过**ppRandomBlock的访问都有未定义的行为。因此,它需要后跟一个*ppRandomBlock = new RANDOMBLOCK
  • 内部的for循环有一条语句(*ppRandomBlock).pRandomData[i] = (char)(rand() % 256),尽管pRandomData[i]的类型是unsigned char。直接的charsigned还是unsigned是由实现定义的。如果设置为signed,则不能保证char能够保存的最大值大于127。这导致转换到char有未定义的行为。

作为部分修复,将RANDOMBLOCK更改为包含std::vector<unsigned char> RandomData,并完全消除ulRandomLenpRandomData成员。然后将函数更改为

unsigned long RandBlockFuncs::GenerateRandomBlock(RANDOM_BLOCK*& ppRandomBlock)
{
    try 
    {
         // assume `srand()` has been called, for example, in main()
      ppRandomBlock = new RANDOM_BLOCK;
      int random = rand() % 129;
      ppRandomBlock.RandomData.resize(random);
      for (int i = 0; i < random; i++)
      {
         ppRandomBlock.RandomData[i] = (unsigned char)(rand() % 256);
      }
      return 0;
   }
   catch (exception& e)
   {
       return -1;
   }
}

请注意,以上并不能解决unsigned返回类型和-1返回值的问题。

更一般地说,OP代码中的首要问题是,它是将一些C代码(带装饰)粗略地翻译成c++。即使它是好的C代码,好的C技术并不总是好的c++技术,反之亦然。而且,从表面上看,原始代码在c中包含了糟糕的技术。

最好完全重写代码以使用c++库特性(我已经演示了其中的一个元素,可能还有更多),并且根本不直接使用操作符new