Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.07.2009, 09:17   #1
Vladss
 
Аватар для Vladss
 
Регистрация: 28.07.2009
Сообщений: 8
Вопрос ошибка при работе с указателем

Программирую недавно, над вопросом бъюсь второй день.
Вопрос следующий: при присвоении значения одного указателя другому, возникает ошибка "Access violation writing location". Что я делаю неправильно? Общий случай:
Код:
void fnReverse(char *str) //переворачиваю строку
{
        char temp;
        int len = strlen(str);
        for(int i = 0; i < len/2; i++) 
        {                   
                temp    =       str[i];    
                str[i]    =       str[wlen-i-1]; //здесь и возникает ошибка
                str[wlen-i-1] = temp;   
        }
}
либо:
Код:
char *fnPlus(char *t, char *s)           //складываю две строки
{
 	char *temp = t;
	while(*s) *t++ = *s++;       //здесь и возникает ошибка
	*t = '\0';
	return temp;
}
Подскажите, пожалуйста, как избежать ошибки?

Последний раз редактировалось Sazary; 28.07.2009 в 15:02.
Vladss вне форума Ответить с цитированием
Старый 28.07.2009, 09:33   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
wlen-i-1
А где wlen вычисляется?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 28.07.2009, 11:02   #3
megachuhancer
Форумчанин
 
Регистрация: 16.04.2009
Сообщений: 247
По умолчанию

fnPlus работает вроде нормально, только она копирует одну строку в другую, а не складывает их. Ошибка может быть, например, из-за того, что нет нулевого символа в пределах s.
megachuhancer вне форума Ответить с цитированием
Старый 28.07.2009, 11:09   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
while(*s) *t++ = *s++; //здесь и возникает ошибка
А с чего ты взял что этот код сложит тебе строки? И почему бы не воспользоваться стандартными функциями?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 28.07.2009, 11:14   #5
pavelstraut
Пользователь
 
Регистрация: 17.07.2009
Сообщений: 91
По умолчанию

скажите что делают эти 2 строки
Код:
int* *c;(особенно это интересует)
int* a;
c=&a;
pavelstraut вне форума Ответить с цитированием
Старый 28.07.2009, 12:06   #6
rangerx
Пользователь
 
Регистрация: 30.05.2009
Сообщений: 46
По умолчанию

В первом случае никакой ошибки, на первый взгляд, быть не должно.
Вопрос скорее в том, что вы передаёте ей в качестве аргумента.
rangerx вне форума Ответить с цитированием
Старый 28.07.2009, 12:16   #7
lennon
Заблокирован
 
Регистрация: 18.11.2007
Сообщений: 254
По умолчанию

str[i] = str[wlen-i-1]; //здесь и возникает ошибка

размер массива не соответсвует wlen-i-1 в какомто такте из циклов, программа обратилася по несуществующему адрессу и поэтому вылетает.

while(*s) *t++ = *s++; //здесь и возникает ошибка
аналогично массив s может быть больше чем массив t тогда шоли условие написть надо так while (*s | *t) вообщем вердикт такой: у тебя memory leaks в этих вдух случаях из за неверного размера "массива- получателя" хехехе
lennon вне форума Ответить с цитированием
Старый 28.07.2009, 13:08   #8
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Так же не могу не обратить внимание на переменную wlen, судя по всему это какая-то глобальная переменная. Это плохой стиль программирования.
Vladss, старайтесь не использовать глобальные переменные, хоть иногда это и наиболее простое решение, передавайте все что нужно функции через ее параметры.
Т.к. в данном случае не известно, как инициализируется wlen, то ошибка, судя по всему, возникает из-за некорректного значения этой переменной (обращение к несуществующему индексу массива, т.е. запрещенной, для данной программы, области памяти). Вообщем объявление wlen - в студию.
Вообще работа с указателям - опасная штука. Нужно быть очень внимательным, особенно при активном их использовании. В Вашем случае указатели используется очень рискованно и неразумно, поэтому вторую функцию предлагаю полностью переписать:

Код:
#include <stdio.h>
#include <malloc.h>
#include <string.h>

char *fnPlus(char *t, char *s)
{
	unsigned int len = strlen(t)+strlen(s)+1; //вычисляем длину итоговой строки
	char *temp = (char*)malloc(len); //выделяем необходимый объем памяти, и создаем указатель на нее - временный буфер
	memcpy(temp, t, strlen(t)); //копируем первую строку в наш буфер
	memcpy(temp+strlen(t), s, strlen(s)); //копируем в остаток буфера вторую
	temp[len-1] = 0; //финальный ноль
	return temp; //возвращаем результат
}
Остается одно большое НО! В функции мы динамически выделяем память, и после выхода из функции память остается выделенной. В результате получаем печальное последствие - утечку памяти, хоть маленькую. Эту память необходимо освободить. В самой функции этого делать нельзя, т.к. если мы сделаем освобождение до return temp; - возвращать уже будет нечего, а если после - этот код выполнятся уже не будет, т.к. функция завершится раньше. Для решения проблемы можно поступить так:
Код:
	char *res = fnPlus("one", "second");
	printf(res);
	free(res);
Результат вызова нашей функции мы присваиваем указателю res, т.е. теперь res = temp и указывают на ОДНУ И ТУ ЖЕ область памяти. Отображаем результат и теперь мы можем смело вызвать free(res); для освобождения занятой памяти.
А вообще, что бы не изобретать велосипед есть замечательные функции:
strcpy и strncpy.
oleg kutkov вне форума Ответить с цитированием
Старый 28.07.2009, 13:48   #9
rangerx
Пользователь
 
Регистрация: 30.05.2009
Сообщений: 46
По умолчанию

вторую можно переписать так:
Код:
void fnPlus(char *dest, char *src, int dest_buf_size) //dest_buf_size это реальный размер dest массива
{
    /*здесь должны быть все необходимые проверки на то хватит ли места для копирования и т.д.
        ...
    */

    char *p = dest + strlen(dest);
    while(*src) *(p++) = *(src++);
}
P.S. Переход к след элементу осуществляется так p++, а не так, как у вас. Так *p++ вы увеличиваете само значение(если вам так будет понятней, то вы по сути делаете p[1]++).
rangerx вне форума Ответить с цитированием
Старый 28.07.2009, 14:02   #10
Vladss
 
Аватар для Vladss
 
Регистрация: 28.07.2009
Сообщений: 8
По умолчанию

от автора))) Спасибо всем за отзыв..........
а)Прошу прощения - в строке
int len = strlen(str) имелось ввиду
int wlen = strlen(str); т.ч. это обычная переменная......
б)цит: "А с чего ты взял что этот код сложит тебе строки? И почему бы не воспользоваться стандартными функциями?" while(*s) *t++ = *s++;
Со стандартными всё ясно! Не могу понять, почему в аналогичных ситуациях я не могу присвоить одниму указателю значение другого! Может быть это очевидно, а может это очевидная чепуха, т.ч. простите за вопрос!
Vladss вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при работе с БД Access Evgen1976 БД в Delphi 8 16.06.2009 21:29
Ошибка при работе с структурой Nullator Общие вопросы C/C++ 11 07.03.2008 23:52
Ошибка при работе с файлом LeoN Общие вопросы Delphi 1 07.12.2007 15:21
Ошибка при работе с БД malevich БД в Delphi 8 25.11.2007 15:10