none
Exception thrown - по непонятной (мне) причине RRS feed

  • Вопрос

  • #include <iostream>

    unsigned char* new_rect(long h, long w) { unsigned char *buf = new unsigned char[h * w]; unsigned int r = 0, g = 0, b = 255; unsigned int index_or_rgb; r = (r << 16); g = (g << 8); b = (b); index_or_rgb = (0xff000000 | r | g | b); for (long y = 0; y < h; y++) { for (long x = 0; x < w; x++) { ((unsigned int*)buf)[y*w + x] = index_or_rgb; } } return buf; } int main() { unsigned char* src = new_rect(100, 600); }

    После запуска данного кода вылетает "Exception thrown: write access violation. buf was 0x111030D0253E112.". Данная ошибка возникает в данном участке кода: 
    ((unsigned int*)buf)[y*w + x] = index_or_rgb;
    у меня данная ошибка возникает при x=236 y=27(хотя если закинут в новый проект, то переменные буду другими). Если подставить эти данные в формулу y*w+x=16 436, а максимальный размер "buf" h*w=60 000, выходит что размер массива не превышен, но если я правильно понимаю ошибку, то он превышен(возможно это связано с приведением типа...). В чём проблема, если можно поподробнее...
    • Изменено provokator1700 13 октября 2020 г. 17:33 уточнил моменты
    13 октября 2020 г. 17:29

Ответы

  • На первый взгляд проблема в том что буфер в sizeof(int)/sizeof(char) раз меньше чем надо. Иными словами, если выделить, скажем, 1000 байтов и попробовать записать 1000 4 байтных слов то буфер может внезапно кончится. :)





    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа provokator1700 13 октября 2020 г. 23:26
    13 октября 2020 г. 18:56
    Модератор
  • Это C, можно что угодно привести к чему угодно. Надо делать это так чтоб оно имело смысл, иначе будет плохо. Память, разумеется, не меняется, что и вызывает выход за границы массива.

    При приведении указателя не происходит ровным счетом ничего, он как был адресом в памяти, так адресом и в памяти и остался.

    Зато меняется вычисление индекса p[i] которое производится по формуле p + (размер того на что указывает указатель) * i.

    char* foo = 1000; // Число просто для примера

    int* bar = (int*)foo; // Указатель совершенно не изменился

    foo[3] - вернет значение байта (считая что char это байт) по адресу 1000 + 1 * 3 = 1003.

    bar[3] - вернет значение 4 байтов (считая что int это 4 байта) по адресу 1000 + 4 * 3 = 1012.



    This posting is provided "AS IS" with no warranties, and confers no rights.


    13 октября 2020 г. 22:52
    Модератор

Все ответы

  • На первый взгляд проблема в том что буфер в sizeof(int)/sizeof(char) раз меньше чем надо. Иными словами, если выделить, скажем, 1000 байтов и попробовать записать 1000 4 байтных слов то буфер может внезапно кончится. :)





    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа provokator1700 13 октября 2020 г. 23:26
    13 октября 2020 г. 18:56
    Модератор
  • Не понимаю как можно указатель на меньший тип(unsigned char) привести к указателю на больший(unsigned int) [от куда появляется дополнительная память(было 8бит(char) и становится 32бит(int))???  ]. Хотя данный код работает верно:

    #include <QtCore/QCoreApplication>
    #include"qimage.h"
    
    void new_rect(long h, long w, unsigned char *buf) {
    	unsigned int r = 0, g = 0, b = 255;
    	unsigned int index_or_rgb;
    	r = (r << 16);
    	g = (g << 8);
    	b = (b);
    	index_or_rgb = (0xff000000 | r | g | b);
    	for (long y = 0; y < h; y++) {
    		for (long x = 0; x < w; x++) {
    			((unsigned int*)buf)[y*w + x] = index_or_rgb;
    		}
    	}
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
    	QImage image(100, 600, QImage::Format_RGB32);
    	new_rect(100, 600, image.bits());
    
        return a.exec();
    }

    И разница между прошлым и этим только в том что выделение памяти "весит" на qt библиотеке QImage. image.bits() - возвращает указатель на unsigned char. Я не могу понять почему так происходит и как... (у меня был указатель на usigned char я явно преобразую его в unsigned int, я не совсем понимаю что происходит на этом этапе), вы написали что памяти меньше в "n" раз, но как происходит преобразование в данном случае, даже если я выделю больше памяти:

    unsigned char*buf=new unsigned char[h* w* sizeof(int)/sizeof(char)] то как после преобразования мой массив станет меньше(размерность - было (h*w* sizeof(int)/sizeof(char)) а после преобразования в int станет (h*w)) если память уже выделена?

    13 октября 2020 г. 19:29
  • Это C, можно что угодно привести к чему угодно. Надо делать это так чтоб оно имело смысл, иначе будет плохо. Память, разумеется, не меняется, что и вызывает выход за границы массива.

    При приведении указателя не происходит ровным счетом ничего, он как был адресом в памяти, так адресом и в памяти и остался.

    Зато меняется вычисление индекса p[i] которое производится по формуле p + (размер того на что указывает указатель) * i.

    char* foo = 1000; // Число просто для примера

    int* bar = (int*)foo; // Указатель совершенно не изменился

    foo[3] - вернет значение байта (считая что char это байт) по адресу 1000 + 1 * 3 = 1003.

    bar[3] - вернет значение 4 байтов (считая что int это 4 байта) по адресу 1000 + 4 * 3 = 1012.



    This posting is provided "AS IS" with no warranties, and confers no rights.


    13 октября 2020 г. 22:52
    Модератор