БлогNot. malloc всему виной?

malloc всему виной?

Интересный баг или фича от Borland C++.

#include <stdio.h>
#include <string.h>
#include <alloc.h>

char *strinsn (char *s, char *t,int n) {
 int l1=strlen(s),l2=strlen(t);
 if (n<0 || n>l1) return NULL;
 char *p=(char *) calloc(l1+l2,sizeof(char));
 return strcat(strcat(strncpy(p,s,n),t),&s[n]);
}

void main () {
 char *s1="abcdef",
  *s2="123";
 int n=3; //may be from 0 to 6 inclusively for this test
 printf ("\n%s",strinsn (s1,s2,n));
}

Запускаем эту простую программку, содержащую единственную функцию char *strinsn (char *s, char *t,int n)

Функция вставляет заданную указателем строку t в строку s, начиная с позиции n. Проверяется допустимость n, далее выделяется память под результирующую строку p (оператор calloc), первые n символов строки s копируются в p (вызов strncpy(p,s,n), который вернет указатель на p), затем к этому p "прицепляется" строка t (получается strcat(strncpy(p,s,n),t), возвращён будет по-прежнему указатель на p), наконец, к полученной строке дописывается "остаток" исходной строки s, начиная с символа под номером n (напомню, что нумерация в Си ведется с нуля, так что он будет n+1-м по порядку).

Внешний вызов strcat также вернёт указатель на первый аргумент, поэтому в результате всей функцией возвращается указатель именно на новую строку p, под которую мы выделили память.

Всё это звучит верно и работает. Проблемы начинаются, когда мы выделяем память методом malloc, а не calloc. Теоретически отличие только в том, что malloc не "забивает" нулями выделяемую им память, плюс размер памяти указывается в байтах единственным аргументом (у calloc первым аргументом передаётся число элементов, вторым - размер каждого элемента в байтах).

В общем, изменённая таким образом программка

#include <stdio.h>
#include <string.h>
#include <alloc.h>

char *strinsn (char *s, char *t,int n) {
 int l1=strlen(s),l2=strlen(t);
 if (n<0 || n>l1) return NULL;
 char *p=(char *) malloc((l1+l2)*sizeof(char));
 return strcat(strcat(strncpy(p,s,n),t),&s[n]);
}

void main () {
 char *s1="abcdef",
  *s2="123";
 int n=3; //may be from 0 to 6 inclusively for this test
 printf ("\n%s",strinsn (s1,s2,n));
}

начинает вести себя странно. Вот выводы для 3 последовательных запусков.

abcDOWS\TEMP\scs22.tmp123def
abcDOWS\TEMP\scs22.tmp123def123def
abcDOWS\TEMP\scs22.tmp123def123def123def

Получиться, как понимаете, должно было во всех случаях

abc123def

Настройки компилятора и проч. были абсолютно одинаковы. Делать "по шагам", освобождать выделяемую память и прочее пробовал, ничего не помогло.

Кто бы объяснил в чём фича :)

Среда - учебная, Вorland C++ 3.1., но в своё время в ней писались вполне серьёзные проекты, в том числе и мной...

09.01.2010, 15:48 [9353 просмотра]


теги: c++ программирование ошибка

показать комментарии (1)