3

I'm simply trying to write to a matrix of a given size. When I run this program in Valgrind, I get memory errors as shown below:

main.cpp:

#include <iostream>
#include <opencv2/opencv.hpp>

int main()
{
    cv::Mat m = cv::Mat::zeros(cv::Size(59, 9), CV_32SC1);
    m.at<int>(9, 4) = 1;
}

Compiling instructions:

g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o binary  main.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching

Finally run Valgrind:

valgrind ./binary

It returns this message on my machine:

==98408== Invalid write of size 4
==98408==    at 0x1000017F8: main (main.cpp:7)
==98408==  Address 0x10dd202cc is 4 bytes after a block of size 2,152 alloc'd
==98408==    at 0x100009EAB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==98408==    by 0x10001D1E6: cv::fastMalloc(unsigned long) (in /usr/local/Cellar/opencv/2.4.12/lib/libopencv_core.2.4.12.dylib)
==98408==    by 0x1000F4C77: cv::Mat::create(int, int const*, int) (in /usr/local/Cellar/opencv/2.4.12/lib/libopencv_core.2.4.12.dylib)
==98408==    by 0x1000F0A51: cv::MatOp_Initializer::assign(cv::MatExpr const&, cv::Mat&, int) const (in /usr/local/Cellar/opencv/2.4.12/lib/libopencv_core.2.4.12.dylib)
==98408==    by 0x1000018FB: cv::MatExpr::operator cv::Mat() const (mat.hpp:1227)
==98408==    by 0x1000017BC: main (main.cpp:6)

These are the specifications of my machine:

Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin15.0.0
Thread model: posix

homebrew/science/opencv 2.4.12
Lenar Hoyt
  • 5,971
  • 6
  • 49
  • 59
  • 1
    I don't know the answer I just wanted to commend such a nicely formatted, detailed question. – GPPK Nov 20 '15 at 10:56
  • @GPPK Thanks. Could you reproduce the same result in Valgrind? – Lenar Hoyt Nov 20 '15 at 11:00
  • 1
    To me, this seems to be a very common source of confusion in OpenCV. Is there any canonical Q&A on that? – anderas Nov 20 '15 at 11:10
  • @anderas this is actually something you'll find out in a sec reading the [doc](http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat-mat): "size – 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the number of columns go in the reverse order." – Miki Nov 20 '15 at 11:19
  • @Miki I know, that's why I answered the question. But I know a few people (including myself) that have to look that up after not working with opencv for some time. That's why I was asking: There might (already/in the future) be questions with the problem being the same confusion. Edit: For example, the answers on http://stackoverflow.com/questions/25642532/opencv-pointx-y-represent-column-row-or-row-column contain a great description of the problem, but in another language and context. Maybe this question here is really a case of the xy problem? – anderas Nov 20 '15 at 11:22
  • 2
    @anderas I didn't find any exact duplicate (if you do, please mark as such). This kind of stuff will fit nicely in the incoming [documentation](http://meta.stackoverflow.com/questions/310066/stack-overflow-serving-programmers-even-better?cb=1) – Miki Nov 20 '15 at 11:25
  • Also similar, but slightly narrower and with worse answers than the other Q I referred to: http://stackoverflow.com/questions/8184053/accessing-elements-of-a-cvmat-with-atfloati-j-is-it-x-y-or-row-col?lq=1 – anderas Nov 20 '15 at 11:27
  • 1
    @anderas both links are basically the same issue as here, only for Point and not for size. I personally won't mark this as duplicate of those. We can always use this as base for future duplicates (probably the question title should be changed a little). – Miki Nov 20 '15 at 11:30
  • I'm feeling pretty dumb now, but it really is confusing. Why would it be `Mat(int rows, int cols, int type)`, but `Mat(Size(int cols, int rows), int type)`? I somehow confused these two when looking it up so I went through the trouble of creating a MWE. – Lenar Hoyt Nov 20 '15 at 12:01
  • The convention is that you access a matrix with (row, col), a point with (x, y), and a size is (width, height). Note that the access for points and sizes is inverted wrt matrices. So it's just a convention, you'll get used to it. – Miki Nov 20 '15 at 14:39

2 Answers2

2

You're accessing the matrix out of bounds.

cv::Mat m = cv::Mat::zeros(cv::Size(59, 9), CV_32SC1);

will create a matrix with 9x59 matrix (9 rows, 59 columns). And you are accessing the 10th row.

Miki
  • 40,887
  • 13
  • 123
  • 202
2

You seem to have the dimensions of your matrix mixed up. You construct a matrix with 59 columns and 9 rows, and access the 10th row and 4th column:

cv::Size(width,height); // size specification
m.at<int>(y,x); // access

So row 9 is out of range. Either swap the dimensions, or the indices!

anderas
  • 5,744
  • 30
  • 49