Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вызов strcpy для char* дважды

11K
29 февраля 2008 года
Salamansar
83 / / 29.11.2006
Доброго всем времени суток!:)
Хочу спросить у вас об одной проблеме, внятного объяснения которой я не смог найти.
Проблема вот в чем:
создаются 3 указателя на char:
 
Код:
char * st1="text", *st2, *st3;

Затем происходит копирование из st1 в st2:
 
Код:
strcpy(st2,st1)

Здесь все проходит хорошо, но
 
Код:
strcpy(st3,st1)
или
 
Код:
strcpy(st3,st2)
выводит ошибку отказа доступа к памяти.

Если же сделать указатели массивами или выделить динамически под них память все проходит как по маслу.

Я сделал альтернативу strcpy:
 
Код:
void copyString(char *in, char *out)
{
for(int i=0; (out=in)!='\0';i++);
}

но ничего не изменилось.

Я понимаю различия между char* и char [], но тем не менее не могу понять, где собака зарыта. :confused:
Почему в первый раз вызывается нормально, а во второй вылетает?
Почему именно с ошибкой запрета доступа к памяти?
Объясните пожалуйста в чем здесь проблема. :confused:

P.S. Использовался компилятор Builder C++ 6.0, если это имеет значение
14K
29 февраля 2008 года
wrap
35 / / 02.06.2006
У тебя st2 и st3 не инициализированы и память не выделена. Т.е. st2 И st3 содержат какие-то "мусорные" значения которые интерпретируются как адреса destination буферов.
4.3K
29 февраля 2008 года
flat
142 / / 27.12.2005
И что удивительного в данной ситуации?? То, что вылетает ошибка, когда происходит обращение к невыделенной памяти?
Цитата:
Почему в первый раз вызывается нормально


Это частный случай, в общем случае - это грубейшая ошибка.

87
29 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Salamansar

Я сделал альтернативу strcpy:
 
Код:
void copyString(char *in, char *out)
{
for(int i=0; (out=in)!='\0';i++);
}

но ничего не изменилось.



Не верю. Наверняка на эту альтернативу уже компилятор ругался, а не программа вылетала.

3
29 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: Kogrom
Не верю. Наверняка на эту альтернативу уже компилятор ругался, а не программа вылетала.


А чего ему ругаться?
Кстати, можно было сделать функцию на основе классического примера:

 
Код:
void copyString(const char* in, char* out)
{
    while(*out++ = *in++);
}
87
29 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Green
А чего ему ругаться?


Происходит обращение к элементам массивов (in, out), которые не были объявлены.
(Изменил ответ, так как ранее он был грубоват и не ясен)

30K
29 февраля 2008 года
Ден Зурин
28 / / 17.02.2008
В чем ошибка, уже было сказано. А вот правильный пример (для Си):
Код:
#include <stdio.h>
#include <string.h>
#include <malloc.h>

int main()
{
char * st1="text", *st2, *st3;
// выделяем память
st2=malloc(strlen(st1)+1);
st3=malloc(strlen(st1)+1);
// копируем строки
strcpy(st2,st1);
strcpy(st3,st1);
// выводим строки
printf("%s\n%s\n%s\n", st1, st2, st3);
// освобождаем память
free(st2);
free(st3);
// конец
return 0;
}

З.Ы. При работе со строками в Билдере обычно используют класс AnsiString. В этом случае память выделяется и освобождается автоматически.
3
29 февраля 2008 года
Green
4.8K / / 20.01.2000
Цитата: Ден Зурин

З.Ы. При работе со строками в Билдере обычно используют класс AnsiString. В этом случае память выделяется и освобождается автоматически.


При работе со строками на C++ обычно используют класс std::string.

36K
29 февраля 2008 года
Trilobit
6 / / 21.02.2008
А ещё есть функция

char *strdup(const char *).

malloc() и strcpy() в одном флаконе.


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

int main()
{
char * st1="text", *st2, *st3;

st2=strdup(st1);
st3=strdup(st1);

// выводим строки
printf("%s\n%s\n%s\n", st1, st2, st3);
// освобождаем память
free(st2);
free(st3);
// конец
return 0;
}
3
01 марта 2008 года
Green
4.8K / / 20.01.2000
Цитата: Kogrom
Происходит обращение к элементам массивов (in, out), которые не были объявлены.
(Изменил ответ, так как ранее он был грубоват и не ясен)


Смотрим стандарт:

Цитата:

5.2.1 Subscripting [expr.sub]

1 A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type “pointer to T” and the other shall have enumeration or integral type. The result is an lvalue of type “T.” The type “T” shall be a completely-defined object type.56) The expression E1[E2] is identical (by definition) to *((E1)+(E2)). [Note: see 5.3 and 5.7 for details of * and + and 8.3.4 for details of arrays. ]

87
01 марта 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Green
Смотрим стандарт:



Извиняюсь. Ошибался. Привык к использованию адресной арифметики при работе с указателями.

11K
03 марта 2008 года
Salamansar
83 / / 29.11.2006
То, что из-за памяти вылетает это понятно, но почему всеже все нормально проходит в первый раз и только потом память для доступа "закрывется"?:confused:

[QUOTE=Ден Зурин]При работе со строками в Билдере обычно используют класс AnsiString. В этом случае память выделяется и освобождается автоматически.[/QUOTE]
[QUOTE=Green]При работе со строками на C++ обычно используют класс std::string.[/QUOTE]
Спасибо за совет, но мне нужно обрабатывать строки именно таким примитивным образом - через char* :)
[QUOTE=Trilobit]
char *strdup(const char *)
[/QUOTE]
Спаисбо, приму к сведению :)
[QUOTE=Kogrom]Не верю. Наверняка на эту альтернативу уже компилятор ругался, а не программа вылетала.[/QUOTE]
Уж поверь - мне врать ни к чему :)
240
03 марта 2008 года
aks
2.5K / / 14.07.2006
Цитата: Salamansar
То, что из-за памяти вылетает это понятно, но почему всеже все нормально проходит в первый раз и только потом память для доступа "закрывется"?:confused:


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

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог