СИ динамический двумернный массив

Модератор: Модераторы разделов

Аватара пользователя
krivakin
Сообщения: 117
ОС: Debian 4.0

СИ динамический двумернный массив

Сообщение krivakin »

Пытаюсь написать программу которая будет выделять память для двумерного делая один раз вызов malloc.

Код: Выделить всё

 1 #include <stdlib.h>
  2 #include <stdio.h>
  3
  4 int main(int argc, char *argv[])
  5 {
  6   int SIZE = atoi(argv[1]);
  7   char **p;
  8   p = (char**)malloc(sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE);
  9   bzero(p, (sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE));
 10   for (int i = 0; i < SIZE; i++) {
 11     p[i] = sizeof(char*) * SIZE + i * SIZE + (long int)&p;
 12   }
 13   for (int i = 0; i < SIZE; i++)
 14     for (int j = 0; j < SIZE; j++)
 15     {
 16       printf("%u %u %u\n", &p[i][j], &p, &p[99][99]);
 17       p[i][j] = 120;
 18     }
 19   free(p);
 20   return 0;
 21 }


При запуске с параметром 100 вылетает segment fault

Код: Выделить всё

Вывод valgrind:
==2766== Invalid write of size 1
==2766==    at 0x80485B9: main (2.c:17)
==2766==  Address 0xbece8000 is not stack'd, malloc'd or (recently) free'd
==2766==
==2766==
==2766== Process terminating with default action of signal 11 (SIGSEGV)
==2766==  Access not within mapped region at address 0xBECE8000
==2766==    at 0x80485B9: main (2.c:17)
==2766==  If you believe this happened as a result of a stack
==2766==  overflow in your program's main thread (unlikely but
==2766==  possible), you can try to increase the size of the
==2766==  main thread stack using the --main-stacksize= flag.
==2766==  The main thread stack size used in this run was 8388608.
==2766==
==2766== HEAP SUMMARY:
==2766==     in use at exit: 10,400 bytes in 1 blocks
==2766==   total heap usage: 1 allocs, 0 frees, 10,400 bytes allocated
==2766==
==2766== LEAK SUMMARY:
==2766==    definitely lost: 0 bytes in 0 blocks
==2766==    indirectly lost: 0 bytes in 0 blocks
==2766==      possibly lost: 0 bytes in 0 blocks
==2766==    still reachable: 10,400 bytes in 1 blocks
==2766==         suppressed: 0 bytes in 0 blocks
==2766== Reachable blocks (those to which a pointer was found) are not shown.
==2766== To see them, rerun with: --leak-check=full --show-reachable=yes
==2766==
==2766== For counts of detected and suppressed errors, rerun with: -v
==2766== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)


P.S. Что то codebox не работает
Спасибо сказали:
Аватара пользователя
eternalStudent
Сообщения: 7
ОС: openSUSE 11.2

Re: СИ динамический двумернный массив

Сообщение eternalStudent »

krivakin писал(а):
11.02.2010 21:10
Пытаюсь написать программу которая будет выделять память для двумерного делая один раз вызов malloc.

Код: Выделить всё

 1 #include <stdlib.h>
  2 #include <stdio.h>
  3
  4 int main(int argc, char *argv[])
  5 {
  6   int SIZE = atoi(argv[1]);
  7   char **p;
  8   p = (char**)malloc(sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE);
  9   bzero(p, (sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE));
 10   for (int i = 0; i < SIZE; i++) {
 11     p[i] = sizeof(char*) * SIZE + i * SIZE + (long int)&p;
 12   }
 13   for (int i = 0; i < SIZE; i++)
 14     for (int j = 0; j < SIZE; j++)
 15     {
 16       printf("%u %u %u\n", &p[i][j], &p, &p[99][99]);
 17       p[i][j] = 120;
 18     }
 19   free(p);
 20   return 0;
 21 }


При запуске с параметром 100 вылетает segment fault

Код: Выделить всё

Вывод valgrind:
==2766== Invalid write of size 1
==2766==    at 0x80485B9: main (2.c:17)
==2766==  Address 0xbece8000 is not stack'd, malloc'd or (recently) free'd
==2766==
==2766==
==2766== Process terminating with default action of signal 11 (SIGSEGV)
==2766==  Access not within mapped region at address 0xBECE8000
==2766==    at 0x80485B9: main (2.c:17)
==2766==  If you believe this happened as a result of a stack
==2766==  overflow in your program's main thread (unlikely but
==2766==  possible), you can try to increase the size of the
==2766==  main thread stack using the --main-stacksize= flag.
==2766==  The main thread stack size used in this run was 8388608.
==2766==
==2766== HEAP SUMMARY:
==2766==     in use at exit: 10,400 bytes in 1 blocks
==2766==   total heap usage: 1 allocs, 0 frees, 10,400 bytes allocated
==2766==
==2766== LEAK SUMMARY:
==2766==    definitely lost: 0 bytes in 0 blocks
==2766==    indirectly lost: 0 bytes in 0 blocks
==2766==      possibly lost: 0 bytes in 0 blocks
==2766==    still reachable: 10,400 bytes in 1 blocks
==2766==         suppressed: 0 bytes in 0 blocks
==2766== Reachable blocks (those to which a pointer was found) are not shown.
==2766== To see them, rerun with: --leak-check=full --show-reachable=yes
==2766==
==2766== For counts of detected and suppressed errors, rerun with: -v
==2766== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)


P.S. Что то codebox не работает


На С++ это делать проще.. Интересный вопрос - хочу сделать (или найти написанную) матричную библиотеку на С++ оптимально работающую.

в строке 11 написано присвоение нового адреса (адреса каждой строки) - это если я правильно понял автора.

Как я думаю, нужно сначала выделить массив "одномерный" (0-й столбец) для типа char* размером SIZE элементов, чтоб хранить указатели на строки

Код: Выделить всё

p = (char**)malloc(sizeof(char*)*SIZE);

а потом для каждого элемента столбца выделить массив типа для char ну тоже размером на SIZE элементов.

Код: Выделить всё

p[i] = (char*)malloc(sizeof(char) * SIZE);

так должно заработать.. и не нужно суммировать как написано в строке 8.
Спасибо сказали:
Аватара пользователя
krivakin
Сообщения: 117
ОС: Debian 4.0

Re: СИ динамический двумернный массив

Сообщение krivakin »

На С++ это делать проще.. Интересный вопрос - хочу сделать (или найти написанную) матричную библиотеку на С++ оптимально работающую.

в строке 11 написано присвоение нового адреса (адреса каждой строки) - это если я правильно понял автора.

Как я думаю, нужно сначала выделить массив "одномерный" (0-й столбец) для типа char* размером SIZE элементов, чтоб хранить указатели на строки

Код: Выделить всё

p = (char**)malloc(sizeof(char*)*SIZE);

а потом для каждого элемента столбца выделить массив типа для char ну тоже размером на SIZE элементов.

Код: Выделить всё

p[i] = (char*)malloc(sizeof(char) * SIZE);

так должно заработать.. и не нужно суммировать как написано в строке 8.


Мне необходимо сделать вызывая malloc только ОДИН раз и именно на си.
Спасибо сказали:
Аватара пользователя
eternalStudent
Сообщения: 7
ОС: openSUSE 11.2

Re: СИ динамический двумернный массив

Сообщение eternalStudent »

можно выделить одномерный массив, но использовать искусственную индексацию элементов.
Спасибо сказали:
Аватара пользователя
krivakin
Сообщения: 117
ОС: Debian 4.0

Re: СИ динамический двумернный массив

Сообщение krivakin »

eternalStudent писал(а):
11.02.2010 22:41
можно выделить одномерный массив, но использовать искусственную индексацию элементов.

Нужено что бы был тип char** (Обязательно).
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: СИ динамический двумернный массив

Сообщение Crazy »

Код: Выделить всё

#include <iostream>
#include <cstdlib>
#include <cstdio>

int main(int argc, char *argv[])
{
  int SIZE = atoi(argv[1]);
  char **p;
  p = (char**)malloc(sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE);
  memset(p, '\0', (sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE));
  char *t=(char*)p;
  for (int i = 0; i < SIZE; i++) {
    p[i] = t+sizeof(char**)*SIZE+i*sizeof(char)*SIZE;
  }
  for (int i = 0; i < SIZE; i++)
  {
    for (int j = 0; j < SIZE; j++)
     {
       p[i][j] = 120;
       printf("%u %u %u\n", &p[i][j], &p, &p[99][99]);
     }
  }
    for (int i = 0; i < SIZE; i++)
  {
    for (int j = 0; j < SIZE; j++)
     {
       p[i][j] = 120;
       std::cout.put(p[i][j]);
     }
     std::cout<<std::endl;
  }
  free(p);
  return 0;
};

Наверно так?

Desipere in loco
Спасибо сказали:
Аватара пользователя
eternalStudent
Сообщения: 7
ОС: openSUSE 11.2

Re: СИ динамический двумернный массив

Сообщение eternalStudent »

krivakin писал(а):
11.02.2010 21:10
Пытаюсь написать программу которая будет выделять память для двумерного делая один раз вызов malloc.

Код: Выделить всё

 1 #include <stdlib.h>
  2 #include <stdio.h>
  3
  4 int main(int argc, char *argv[])
  5 {
  6   int SIZE = atoi(argv[1]);
  7   char **p;
  8   p = (char**)malloc(sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE);
  9   bzero(p, (sizeof(char*) * SIZE + sizeof(char) * SIZE * SIZE));
 10   for (int i = 0; i < SIZE; i++) {
 11     p[i] = sizeof(char*) * SIZE + i * SIZE + (long int)&p;
 12   }
 13   for (int i = 0; i < SIZE; i++)
 14     for (int j = 0; j < SIZE; j++)
 15     {
 16       printf("%u %u %u\n", &p[i][j], &p, &p[99][99]);
 17       p[i][j] = 120;
 18     }
 19   free(p);
 20   return 0;
 21 }


При запуске с параметром 100 вылетает segment fault

Код: Выделить всё

Вывод valgrind:
==2766== Invalid write of size 1
==2766==    at 0x80485B9: main (2.c:17)
==2766==  Address 0xbece8000 is not stack'd, malloc'd or (recently) free'd
==2766==
==2766==
==2766== Process terminating with default action of signal 11 (SIGSEGV)
==2766==  Access not within mapped region at address 0xBECE8000
==2766==    at 0x80485B9: main (2.c:17)
==2766==  If you believe this happened as a result of a stack
==2766==  overflow in your program's main thread (unlikely but
==2766==  possible), you can try to increase the size of the
==2766==  main thread stack using the --main-stacksize= flag.
==2766==  The main thread stack size used in this run was 8388608.
==2766==
==2766== HEAP SUMMARY:
==2766==     in use at exit: 10,400 bytes in 1 blocks
==2766==   total heap usage: 1 allocs, 0 frees, 10,400 bytes allocated
==2766==
==2766== LEAK SUMMARY:
==2766==    definitely lost: 0 bytes in 0 blocks
==2766==    indirectly lost: 0 bytes in 0 blocks
==2766==      possibly lost: 0 bytes in 0 blocks
==2766==    still reachable: 10,400 bytes in 1 blocks
==2766==         suppressed: 0 bytes in 0 blocks
==2766== Reachable blocks (those to which a pointer was found) are not shown.
==2766== To see them, rerun with: --leak-check=full --show-reachable=yes
==2766==
==2766== For counts of detected and suppressed errors, rerun with: -v
==2766== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)


P.S. Что то codebox не работает


попробовал присвоить значение переменной SIZE не через параметр. работает. может нужно

Код: Выделить всё

  6   int SIZE = atoi(argv[0]);

по крайней мере ошибки фрагментирования не выдает..

PS: Для успешной компиляции пришлось изменить строку

Код: Выделить всё

p[i] = sizeof(char*) * SIZE + i * SIZE + (long int)&p;

на

Код: Выделить всё

p[i] = sizeof(char*) * SIZE + i * SIZE + (char*)p;

т.к. компилятор не мог конвертировать из long int в char*
и для bzero добавил заголовочный файл

Код: Выделить всё

#include <string.h>
Спасибо сказали:
Аватара пользователя
krivakin
Сообщения: 117
ОС: Debian 4.0

Re: СИ динамический двумернный массив

Сообщение krivakin »

попробовал присвоить значение переменной SIZE не через параметр. работает. может нужно

Код: Выделить всё

  6   int SIZE = atoi(argv[0]);

по крайней мере ошибки фрагментирования не выдает..


argv[0] - это будет имя файла который запускаешь, а не аргумент передоваемый программе.
Спасибо сказали:
Аватара пользователя
krivakin
Сообщения: 117
ОС: Debian 4.0

Re: СИ динамический двумернный массив

Сообщение krivakin »

Вопрос снят, действительно надо было написать:
p[i] = sizeof(char*) * SIZE + i * SIZE + (long int)p;
Спасибо сказали: