0
#define ARRAY_SIZE 20

float DataSource[ARRAY_SIZE];

void Read(unsigned char const *Source, unsigned char *Destination, unsigned long DataSize)
{
  for ( unsigned long i = 0; i < DataSize; i++)
  {
    *(Destination + i*DataSize) = *(Source + i*DataSize);
  }
}

void fun()
{
  int Index;
  float Dest;

  for ( Index = 0; Index < ARRAY_SIZE; Index++ )
  {
    Read((unsigned char *)&DataSource[Index], (unsigned char *)&Dest, sizeof(DataSource[Index]));
  }
}

我在上面的代码中遇到问题,在调用 Read() 时,我的 Index 变量被覆盖,我确信丑陋的指针转换是罪魁祸首,但我无法准确理解这里发生的事情。

unsigned char 指针类型是强制性的,因为上面的代码旨在模拟一些驱动程序级别的软件并保持相同的原型。

有人可以帮我理解这里的问题吗?除了 Read() 的原型之外,上述所有代码都是可以更改的。

4

6 回答 6

4

错误在这里:

for ( unsigned long i = 0; i < DataSize; i++)
{
  //              vvvvvvvvvv               vvvvvvvvvv
  *(Destination + i*DataSize) = *(Source + i*DataSize);
}

i * DataSize总是大于i=>“越界”访问。

用。。。来代替:

for ( unsigned long i = 0; i < DataSize; i++)
{
  *(Destination + i) = *(Source + i);
}
于 2013-01-10T22:12:20.593 回答
2

您将单个float的地址传递给Read ( &Dest),然后继续将许多值写入连续的内存位置。由于此时您正在编写随机内存,因此它不太可能被覆盖index(和其他内容),因为堆栈通常会向下增长。

于 2013-01-10T22:12:39.697 回答
1

一种有趣的(对我而言)C++ 方式。

template<typename Data>
struct MemBlockRefHelper {
  typedef Data value_type;
  Data* data;
  size_t size;
  MemBlockRefHelper( Data* d, size_t s):data(d), size(s) {}

  template<typename Target, typename Other=typename Target::value_type>
  Target& Assign( MemBlockRefHelper<Other> const& other ) {
    Assert(size == other.size);
    for (size_t i = 0; i < size; ++i) {
      if (i < other.size) {
        data[i] = other.data[i];
      } else {
        data[i] = 0;
      }
    }
    Target* self = static_cast<Target*>(this);
    return *self;
  }

};
struct MemBlockRef;
struct MemBlockCRef:MemBlockRefHelper<const unsigned char> {
  MemBlockCRef( const unsigned char* d, size_t s ):MemBlockRefHelper<const unsigned char>( d, s ) {}
  MemBlockCRef( const MemBlockRef& other );
};
struct MemBlockRef:MemBlockRefHelper<unsigned char> {
  MemBlockRef( unsigned char* d, size_t s ):MemBlockRefHelper<unsigned char>( d, s ) {}
  MemBlockRef& operator=( MemBlockRef const& other ) {
    return Assign< MemBlockRef >( other );
  }
  MemBlockRef& operator=( MemBlockCRef const& other ) {
    return Assign< MemBlockRef, const unsigned char >( other );
  }
};
inline MemBlockCRef::MemBlockCRef( const MemBlockRef& other ): MemBlockRefHelper<const unsigned char>( other.data, other.size ) {}

void Read( unsigned char const* Source, unsigned char* Dest, unsigned long DataSize ) {
  MemBlockCRef src( Source, DataSize );
  MemBlockRef dest( Dest, DataSize );
  dest = src;
}

大规模过度设计,但想法是总结一定大小的 POD 内存块的想法,并为其内容提供引用语义(初始化是创建对相同数据的新引用,赋值对引用的数据进行复制到数据)。

一旦你有了这样的类,代码就Read变成了 3 行。好吧,您可以一次性完成:

  MemBlockRef( Dest, DataSize ) = MemBlockCRef( Source, DataSize );

但这是不必要的。

好吧,这就是整个框架。

但写下来我觉得很有趣。

于 2013-01-10T22:28:20.357 回答
1

这是错误的:

*(Destination + i*DataSize) = *(Source + i*DataSize);

你想复制DataSize相邻的字节,而不是DataSize分开的字节(总跨度DataSize*DataSize

说啊

Destination[i] = Source[i];
于 2013-01-10T22:12:55.017 回答
0

Dest您正在将内部声明的标量变量fun()视为内部数组Read()。似乎两者Dest和您的Index变量都相邻放置在堆栈上,这解释了Index当内部循环执行时恰好被覆盖Read()for i==1

所以解决方案是:也声明Dest为数组:

float Dest[ARRAY_SIZE];
于 2013-01-10T22:32:26.613 回答
0

让我们仔细看看您的Read():i 从 0 变为 DataSize-1;每次您以 i*DataSize... 的偏移量访问内存时,即从 0 到 DataSize*(DataSize-1) 的偏移量。看起来不对,因为DataSize**2-DataSize没有意义。

与其他答案不同,我不想猜测您想要什么。只是展示一种“维度分析”,可以帮助发现代码中最错误的部分,而无需阅读作者的想法。

于 2013-01-10T22:15:16.883 回答