1

The code:

unsigned char data[20][20] = 
  {{50, 50....},
  ....
  ....};

Mat speed(20, 20, data);

When I try to access contents in speed.data, it says:

Exception thrown at 0x003D2094 in speed tracking.exe: 0xC0000005: Access violation reading location 0x32323233.

For example, std::cout << img.data[0][1];.

In another file mat.h, the definition of Mat is:

// two-dimensional matrix, type of data is unsigned char
class Mat {
 public:
  Mat(size_t rows_, size_t cols_, void* data_ = nullptr)
      : rows(rows_), cols(cols_), data((unsigned char**)data_) {}
  Mat() : rows(0), cols(0), data(nullptr) {}
  bool empty() const; // return true if data == nullptr
  size_t rows, cols; // the size of the matrix
  unsigned char** data; // the contents of the matrix
};

So why can't I access contents in speed.data?

yikouniao
  • 921
  • 1
  • 8
  • 15
  • Please post a http://stackoverflow.com/help/mcve , I cannot reproduce your error. – dkg Mar 15 '16 at 10:01
  • Access at which index? And where? Same scope where you define data variable? Do you properly cast back to unsigned char in your access code? – BitTickler Mar 15 '16 at 10:02
  • 5
    Arrays are NOT pointers and casting (the pointer to the first element of) array to pointer pointing to another type will produce invalid data. – MikeCAT Mar 15 '16 at 10:03
  • 2
    Think for just a moment, what `0x32` is as a decimal value? Where do we see that? Perhaps in your initialization list? a `char[20][20]` (an array of arrays) is **not** equivalent to pointer-to-pointer-to `char`. Hiding that fact by passing `void*` and hard casting to `char**` doesn't fix anything. – WhozCraig Mar 15 '16 at 10:05
  • @WhozCraig Is there any good way to fix it by modifying `class Mat`? – yikouniao Mar 15 '16 at 10:13
  • Possible duplicate of [How do I work with dynamic multi-dimensional arrays in C?](http://stackoverflow.com/questions/917783/how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c) – MicroVirus Mar 15 '16 at 10:18
  • http://stackoverflow.com/a/17000418/2079934 shows an example to correctly index a multidimensional array. – SpamBot Mar 15 '16 at 10:19

2 Answers2

4

In fact, you do the incorrect cast assigning Mat::data = data because the left side has the type of unsigned char** and the right side has the type of unsigned char (*)[20].

Suppose that after such error-prone casting you try to access some array elements via Mat::data, for example evaluating Mat::data[0][1] (which is a bad idea, of course).

Recall that Mat::data[0][1] = *(*(Mat::data + 0) + 1).

Mat::data + 0 has the type of unsigned char** and value which is equal to the address of the data array.

Then *(Mat::data + 0) has the type of unsigned char* and value which we'll calculate now.

As I can see from the posted crash report, on your machine addresses are 4-byte long. So the first 4 elements of data array are treated as the value of *(Mat::data + 0). Then we add 1 (sizeof(char)) and get *(Mat::data + 0) + 1 value. The result in 16-base is equal to 0x32323233. After that we try to read something from this location, which is the actual reason of SIGSEGV.

It's better to store the address of the first element of array using unsigned char* and use matrix width and height, which are known, to get appropriate matrix elements.

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
2

Mat expects a flat array, so replace unsigned char** data in class Mat with unsigned char*.

The data at (x,y) can be accessed using data + x * cols + y.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
yikouniao
  • 921
  • 1
  • 8
  • 15