powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / strcat - ошибка
62 сообщений из 62, показаны все 3 страниц
strcat - ошибка
    #38042313
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет. Не могу разобраться, как правильно работать с strcat.
Пишу такое, и получаю ошибку:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult;
stringResult = strcat(myString,"as");


Что делаю неправильно?
[strcat] возвращает указатель, я его значение присваиваю другому указателю. Это как вот такое сделать:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult;
stringResult = myString;


Так все работает.
Заранее спасибо за помощь!
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042315
Westtrd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximuS_G,

Кто память будет выделять?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042317
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GВсем привет. Не могу разобраться, как правильно работать с strcat.
Пишу такое, и получаю ошибку:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult;
stringResult = strcat(myString,"as");


Что делаю неправильно?
Строка:
char *myString = "hello";
Означает: Выделить в памяти принадлежащей сегменту кода кусочек в шесть байт, записать туда пять букв h, e, l, l, o и закончить нулем. После этого выделить на стеке кусочек памяти размером в адрес и записать в эту память адрес первого куска.


char *stringResult;
Означает: Выделить на стеке кусочек памяти размером в адрес, ничего туда не писать.

stringResult = strcat(myString,"as");
Означает: Найти в первом куске памяти (который длиной шесть байт) нулевой байт. Записать на место этого нулевого байта букву a, потом в следующий байт записать букву s, потом записать ноль. Потом записать адрес первого куска памяти в третий.

А если теперь внимательно подумать, мы сможем заметить что когда в самом начале мы выделяли первый кусок в шесть байт размером мы не оговаривали что будет находится после него. Соотвественно когда мы пишем седьмую букву s эта буква попадает в неизвестно куда с неизвестно какими последствиями. Вариантов последствий очень много, и все они зависят от конкретной OS в которой ты пытаешься это сделать, компилятора который ты используешь и даже настроек этого компилятора.
В некоторых случаях это может даже работать и ты ничего не заметишь. Но к счастью, в данном случае ты "получил ошибку", рискну предположить что это "попытка записи в сегмент для чтения", так?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042318
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Westtrd
Спасибо за подсказку. Но ведь во втором примере не выделяется память?
Или в первом примере нужно выделять память под "hello", и под "helloas"? Ну так я тоже получаю ошибку:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult = new char[10];
stringResult = strcat(myString,"as");
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042320
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owlрискну предположить что это "попытка записи в сегмент для чтения", так?

Если у него достаточно свежий компилятор, то это скорее сообщение о несовместимости char*
и const char* ещё при компиляции.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042321
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G Westtrd
Спасибо за подсказку. Но ведь во втором примере не выделяется память?
Или в первом примере нужно выделять память под "hello", и под "helloas"? Ну так я тоже получаю ошибку:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult = new char[10];
stringResult = strcat(myString,"as");

А так, память которую ты выделил во второй строке просто теряется. В третей строке ты перенаправляешь указатель на "hello" а те десять байт остаются висеть всеми забытыми. Ты их теперь даже освободить не можешь, потому что не знаешь где они находятся.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042322
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ошибка такая
Unhandled exception at 0x0f74d32a in 17.11.exe: 0xC0000005: Access violation writing location 0x0020bc71.
White Owl
Спасибо за подробно расписанное объяснение. Но постом выше я привел кусок кода, где я выделяю память, но все равно получаю ошибку.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042324
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlMaximuS_G Westtrd
Спасибо за подсказку. Но ведь во втором примере не выделяется память?
Или в первом примере нужно выделять память под "hello", и под "helloas"? Ну так я тоже получаю ошибку:
Код: plaintext
1.
2.
3.
char *myString = "hello";
char *stringResult = new char[10];
stringResult = strcat(myString,"as");

А так, память которую ты выделил во второй строке просто теряется. В третей строке ты перенаправляешь указатель на "hello" а те десять байт остаются висеть всеми забытыми. Ты их теперь даже освободить не можешь, потому что не знаешь где они находятся.

Так а как правильно сделать? :)
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042325
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GОшибка такая
Unhandled exception at 0x0f74d32a in 17.11.exe: 0xC0000005: Access violation writing location 0x0020bc71.
White Owl
Спасибо за подробно расписанное объяснение. Но постом выше я привел кусок кода, где я выделяю память, но все равно получаю ошибку.Ты не понимаешь смысла strcat(). Эта функция не манипулирует строками. Она их не копирует, и не переносит.
Она берет два указателя. Сначала она двигает первый указатель до тех пор пока он не покажет на ячейку памяти в которой записан ноль. После этого она начнет двигать оба указателя разом и копировать байтик из ячейкие на которой показывает второй указатель в ячейку на которую показывает первый, до тех пока второй указатель не покажет на ячейку с нулем.
После этого strcat() вернет копию первого указателя каким он был в самом начале.
Так понятно?

И вообще, разберись пожалуйста на каком языке ты пишешь. На C или C++? Не надо их смешивать, они хоть и похожие, но все-же разные.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042326
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GWhite Owlпропущено...
А так, память которую ты выделил во второй строке просто теряется. В третей строке ты перенаправляешь указатель на "hello" а те десять байт остаются висеть всеми забытыми. Ты их теперь даже освободить не можешь, потому что не знаешь где они находятся.

Так а как правильно сделать? :)А вот это ты должен сам догадаться. Мы можем пояснять некоторые непонятные моменты, но если мы сделаем за тебя такую элементарную задачу - нам придется за тебя и диплом и зарплату получать. А ты ж наверное сам хочешь и диплом и зарплату?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042327
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl
White Owl...Так понятно?
Спасибо, это понял. Но не пойму тогда что здесь не так:
Код: plaintext
1.
2.
3.
char *myString = "hello\0111";
myString = strcat(myString,"as");
cout<<myString;


Под myString выделено 9 байт. "\0" функция найдет, и после него еще есть место, куда приделать "as". Что не нравиться с++? :)
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042332
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G White Owl
White Owl...Так понятно?
Спасибо, это понял. Но не пойму тогда что здесь не так:
Код: plaintext
1.
2.
3.
char *myString = "hello\0111";
myString = strcat(myString,"as");
cout<<myString;


Под myString выделено 9 байт. "\0" функция найдет, и после него еще есть место, куда приделать "as". Что не нравиться с++? :)С++ нравится все. А вот ОС нравится не все.
Читай внимательнее мой первый пост. То где я говорил о "сегментах".
Память она разная бывает. Бывает память на стеке, бывает на куче, бывает в сегменте данных, бывает в сегменте кода, бывает общая, бывает отображенная, много их... Вот только простой памяти не бывает. "Просто" память это из разряда беллетристики и киноляпов.
Так вот "hello" (как и "as" и "hello\0111") записываются компилятором либо в сегмент кода, либо в сегмент данных, либо в сегмент константных данных. Это зависит от компилятора и его настроек. А ОС считает что сегменты кода и сегменты константных данных это сегменты только для чтения. Писать туда нельзя вообще, а тот кто туда пишет - злобный вирус и вообще враг всего доброго и светлого, а значит должен быть убит через Access violation.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042660
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl
Наверное Вы правы, я не очень понимаю, зачем нужна эта функция, и поэтому пытаюсь что-то нагородить.
Можете привести пример самый банальный использования этой функции?
У меня следующая задача.
Есть структура, и я хочу ее свойства записать в другое свойство через слеш:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
struct videoShop
{
	char *movieName;
	char *producer;
	char *compString;
};

videoShop object1;
object1.movieName = "robocop";
object1.producer = "cameron";


У меня задача получить в object1.compString такую строку "robocop/cameron" . Вот я и хотел объединить эти свойства с помощью функции strcat .
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042679
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G,
Если вы уже используете С++ так используйте все его возможности
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <string>
struct videoShop
{
	std::string movieName;
	std::string producer;
	std::string compString;
};

int main()
{
  videoShop object1;
  object1.movieName = "robocop";
  object1.producer = "cameron";
  object1.compString = object1.movieName + "/" + object1.producer;
  return 0;
}



Или обоснуйте почему надо использовать именно С-шные строки (char*).
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042683
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky
Спасибо за подсказку. Я просто еще не учил класс string.
Буду знать, что так можно, так конечно для моего восприятия легче - я на javascript пишу :).
Но сейчас хочу разобраться как работать со строками как с массивом char, вдруг в будущем понадобиться.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
int main()
{
  videoShop object1;
  object1.movieName = "robocop";
  object1.producer = "cameron";
  object1.compString = object1.movieName + "/" + object1.producer;
  return 0;
}


Подскажите, пожалуйста, а зачем Вы объявляете функцию main как такую, которая возвращает значение int?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042689
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_GПодскажите, пожалуйста, а зачем Вы объявляете функцию main как такую, которая возвращает значение int?
Хотя многие компиляторы пропускают и void, но по стандарту положено int. (Возвращаемый из main код - это код выхода приложения, 0 - нормальный выход, не 0 - ошибка )
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042690
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximuS_G White Owl
Наверное Вы правы, я не очень понимаю, зачем нужна эта функция, и поэтому пытаюсь что-то нагородить.
Можете привести пример самый банальный использования этой функции?
У меня следующая задача.
Есть структура, и я хочу ее свойства записать в другое свойство через слеш:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
struct videoShop
{
	char *movieName;
	char *producer;
	char *compString;
};

videoShop object1;
object1.movieName = "robocop";
object1.producer = "cameron";


У меня задача получить в object1.compString такую строку "robocop/cameron" . Вот я и хотел объединить эти свойства с помощью функции strcat .

На чистом C это так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop");
 strcpy(object1.producer, "cameron");

 strcat(object1.compString, object1.movieName);
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}



На С++ как у Anatoly Moskovsky.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042692
Anatoly MoskovskyMaximuS_GПодскажите, пожалуйста, а зачем Вы объявляете функцию main как такую, которая возвращает значение int?
Хотя многие компиляторы пропускают и void, но по стандарту положено int. (Возвращаемый из main код - это код выхода приложения, 0 - нормальный выход, не 0 - ошибка )
А параметры в скобках функции main по стандарту обязательны или там что угодно допускается?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042701
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CНа чистом C это так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop");
 strcpy(object1.producer, "cameron");

 strcat(object1.compString, object1.movieName);
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}

Жуть! не надо так писать.
Ошибка раз - помрет если строки movie и producer будут в сумме длиннее 50 символов.
Ошибка два - чистить надо приемный буфер прежде чем что-то к нему приклеивать.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
struct videoShop
{
	char *movieName;
	char *producer;
	char *compString;
};

int main() {
   videoShop object1;
   object1.movieName = "robocop";
   object1.producer = "cameron";

   // сначала выделить память под приемник
   object1.compString = malloc( strlen(object1.movieName) + strlen(object1.producer) + 2);

   // потом копировать
   strcpy(object1.compString, object1.movieName);
   strcat(object1.compString, "/");
   strcat(object1.compString, object1.producer);

   // а можно проще:
   sprintf(object1.compString, "%s/%s", object1.movieName, object1.producer);

   return 0;
}
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042709
MaximuS_G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CНа чистом C это так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop");
 strcpy(object1.producer, "cameron");

 strcat(object1.compString, object1.movieName);
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}


Спасибо за ответ. Вы тоже используете функци strcat , вот я не могу понять, почему у меня не получалось. Сейчас буду думать, чем мой вариант отличается.
И у меня паралельный вопрос появился - вы создаете структуру и сразу определяете максимальное количество элементов в свойствах. Я создаю структуру с указателями, и потом в коде сколько мне понадобиться символов, столько я и создам, а потом скопирую указатель на массив. Чем такой подход плох?
Спасибо!
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042711
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximuS_G Anatoly Moskovsky
Спасибо за подсказку. Я просто еще не учил класс string.
Буду знать, что так можно, так конечно для моего восприятия легче - я на javascript пишу :).
Но сейчас хочу разобраться как работать со строками как с массивом char, вдруг в будущем понадобиться.


Про строки как массив (С-строки).

Первое что надо понимать, что "строка" это константа являющаяся массивом char. Даже если какие-то компиляторы и позволяют изменить эту константу - это баг (хотя в первую очередь это баг в ваше программе).

Дальше.
char* s - это не сама строка, а указатель на строку (массив char).
Массив char (а значит и строку) можно присвоить в указатель, но при этом присваивается не сам массив, а указатель на его начало.
Код: plaintext
1.
2.
const char* s = "aaa"; // присваиваем указатель на "ааа". 
// const - чтобы не было попыток модифицировать через указатель константу на которую он указывает



Дальше. Мы можем объявить явно массив char и присвоить ему строку/массив. В этом случае создается копия, котоая уже не константа.
Код: plaintext
1.
char s[] = "aaa"; //  массив размером 4 (включая завершающий 0) и скопировали туда строку



Чаще всего размер строки на этапе компиляции неизвестен, поэтому обычно такие массивы (их еще называют статическими, т.к. их размер вычисляется при компиляции и не может меняться при исполнении программы) не применяют, а применяют динамическое выделение памяти через new.
Определяют размер строки через strlen, потом выделяют динамический массив через malloc(len +1 ) или new char[len + 1] (помним про завершающий 0, который не учитывается strlen), потом копируют strcpy. Для случая malloc, есть стандартная функция для всего процесса копирования - strdup.
malloc/new возвращает указатель на созданный динамический массив.
При этом если у нас два указателя, один на статический а другой на динамический массив, то компилятор никак не различает их. В обоих случаях это char*.

Теперь важное. Память выделенную через malloc/new надо освобождать вручную через free/delete. А статический массив наоборот - не надо удалять. Но если мы имеем просто указатель, то мы не знаем это указатель на статический массив или динамический. И не можем принять решение удалять или нет.

Тут есть два варианта. 1) - я его считаю неудачным и никогда не применяю - хранить в структуре вместе с указателем и флаг типа bool с признаком динамического массива (как наиболее тупая вариация - флаг не хранить а помнить что такое-то поле в структуре это динамический массив)
2) Всегда использовать динамические массивы когда в структуре данных хранятся указатели на строки. В случае если строка задана литералом "ааа" то копировать ее в динамический массив.

Таким образом применяя все вышеперечисленное к последнему примеру получаем такое (так как речь все-таки про С, то используем С-шный malloc/free):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
struct videoShop
{
	char *movieName;
	char *producer;
	char *compString;
};

int main()
{
  struct videoShop object1;
  object1.movieName = strdup("robocop"); // скопировали встроенной ф-ей
  object1.producer = strdup("cameron"); // скопировали 
  // тут сначала выделяем память под всю конечную строку включая 0
  object1.compString = (char*)malloc(strlen(object1.movieName) + strlen("/") + strlen(object1.producer) + 1);
  strcpy(object1.compString, object1.movieName); // копируем сначала первую часть строке
  strcat(object1.compString, "/"); // добавляем /
  strcpy(object1.compString, object1.producer); // добавляем вторую часть
  ...
  // удаляем все строки
  free(object1.movieName);
  free(object1.producer);
  free(object1.compString);
  return 0;
}
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042715
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут была опечатка: strcpy в третьей строке должно быть strcat
Код: plaintext
1.
2.
3.
  strcpy(object1.compString, object1.movieName); // копируем сначала первую часть строке
  strcat(object1.compString, "/"); // добавляем /
  strcat(object1.compString, object1.producer); // добавляем вторую часть
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042724
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в скобках функции mainА параметры в скобках функции main по стандарту обязательны или там что угодно допускается?
Их можно опускать справа налево.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042732
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlНа чистом CНа чистом C это так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop");
 strcpy(object1.producer, "cameron");

 strcat(object1.compString, object1.movieName);
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}

Жуть! не надо так писать.
Ошибка раз - помрет если строки movie и producer будут в сумме длиннее 50 символов.
Ошибка два - чистить надо приемный буфер прежде чем что-то к нему приклеивать.


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
struct videoShop
{
	char *movieName;
	char *producer;
	char *compString;
};

int main() {
   videoShop object1;
   object1.movieName = "robocop";
   object1.producer = "cameron";

   // сначала выделить память под приемник
   object1.compString = malloc( strlen(object1.movieName) + strlen(object1.producer) + 2);

   // потом копировать
   strcpy(object1.compString, object1.movieName);
   strcat(object1.compString, "/");
   strcat(object1.compString, object1.producer);

   // а можно проще:
   sprintf(object1.compString, "%s/%s", object1.movieName, object1.producer);

   return 0;
}


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


А насчет чистки, согласен, но вполне достаточно \0 в конце каждой строки.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop\0 aaa");  // edit
 strcpy(object1.producer, "cameron\0");       // edit

 strcpy(object1.compString, object1.movieName);  // edit
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042736
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом Cвполне достаточно \0 в конце каждой строки.
А что, без этого там терминаторов не будет?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042745
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximuS_GНа чистом CНа чистом C это так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <stdio.h>
#include <string.h>

struct videoShop
{
	char movieName[50];
	char producer[50];
	char compString[50];
};


int main(void) {
 struct videoShop object1;
 strcpy(object1.movieName, "robocop");
 strcpy(object1.producer, "cameron");

 strcat(object1.compString, object1.movieName);
 strcat(object1.compString, "/");
 strcat(object1.compString, object1.producer);
 printf ("str1: %s\nstr2: %s\nstr3: %s\n", 
  object1.movieName, object1.producer, object1.compString);

 return 0;
}


Спасибо за ответ. Вы тоже используете функци strcat , вот я не могу понять, почему у меня не получалось. Сейчас буду думать, чем мой вариант отличается.
И у меня паралельный вопрос появился - вы создаете структуру и сразу определяете максимальное количество элементов в свойствах. Я создаю структуру с указателями, и потом в коде сколько мне понадобиться символов, столько я и создам, а потом скопирую указатель на массив. Чем такой подход плох?
Спасибо!
Если заранее определить максимальное количество элементов (как у меня задать массив), то все 3 массива структуры будут лежать рядом, и если затем создать массив структур struct videoShop object2[1000000]; то все структуры и все их элементы будут лежать рядом в памяти, и доступ будет значительно быстрее.

Если использовать strdup() или malloc(), то указатели будут в одном месте рядом, а выделенные строки разбросаны в памяти, что замедлит к ним доступ. Помимо этого нужно будет будет освобождать память используя free(), чтобы не было утечек памяти.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042747
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovНа чистом Cвполне достаточно \0 в конце каждой строки.
А что, без этого там терминаторов не будет?..

Будут конечно :)
Явное использование \0 в строках - бессмысленно.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042751
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом Cдоступ будет значительно быстрее.
Прежде чем оптимизировать, посмотрите на предметную область.
Никого не интересует скорость когда речь фактически идет про базу данных.

Тем более что никакого "значительно быстрее" не будет. Максимум доли процента.
Т.к. типичная программа такого рода однопоточная и никаких конкрурентных обращений к куче не будет.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042755
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТем более что никакого "значительно быстрее" не будет. Максимум доли процента.

А в замен вы вводите лимит на размеры данных, о котором никто не просил, а также накладные расходы по хранению больших массивов с запасом, хотя типичные данные в несколько раз меньше размером.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042757
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНа чистом Cдоступ будет значительно быстрее.
Прежде чем оптимизировать, посмотрите на предметную область.
Никого не интересует скорость когда речь фактически идет про базу данных.

Тем более что никакого "значительно быстрее" не будет. Максимум доли процента.
Т.к. типичная программа такого рода однопоточная и никаких конкрурентных обращений к куче не будет.
Префетчем можно будет достать в L3/L2 весь массив структур, а в случае с динамической вытащим только указатели, а каждый элемент - 300 тактов задержки на обращение к RAM.
Использование чистого C, как бы намекает на необходимость в скорости.
Оптимизировать все подряд конечно не надо, но использование статического массива, вместо динамического - это и быстрее, и удобней без необходимости выделения, освобождения и проверки на NULL перед использованием.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042762
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyAnatoly MoskovskyТем более что никакого "значительно быстрее" не будет. Максимум доли процента.

А в замен вы вводите лимит на размеры данных, о котором никто не просил, а также накладные расходы по хранению больших массивов с запасом, хотя типичные данные в несколько раз меньше размером.
А проблемы динамической памяти: утечки памяти, обращение к невыделенной/освобожденной памяти, время на выделение/освобождение, накладные расходы на дефрагментацию и хранение в куче.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042763
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CПрефетчем можно будет достать в L3/L2 весь массив структур, а в случае с динамической вытащим только указатели, а каждый элемент - 300 тактов задержки на обращение к RAM.

Максимум доли процента выигрыша.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042767
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CА проблемы динамической памяти: утечки памяти, обращение к невыделенной/освобожденной памяти
Только утечки.
Но на то и С++ и std::string, чтобы не заботиться об этом.
Обращение к невыделенной/освобожденной памяти - это касается и массивов, только там будет неинициализированная память.
Про скорость - уже сказал.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042769
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНа чистом CПрефетчем можно будет достать в L3/L2 весь массив структур, а в случае с динамической вытащим только указатели, а каждый элемент - 300 тактов задержки на обращение к RAM.

Максимум доли процента выигрыша.
Смотря какая задача. Непосредственно в этом месте:
1. для статического: 100нс латентности + (1000000 элементов * 150 байт / 40 ГБ/c) = 100 + 4000000 = 4 мс.
2. для динамеческого: 100нс * 1000000 э + (1000000 элементов * 150 байт / 40 ГБ/c) = 104 мс.

Учитываем, что в случае динамического может многократно освобождаться/выделяться память под новый размер строки, тем самым дефрагментируя память.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042770
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Точнее фрагментируя :)
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042773
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНа чистом CА проблемы динамической памяти: утечки памяти, обращение к невыделенной/освобожденной памяти
Только утечки.
Но на то и С++ и std::string, чтобы не заботиться об этом.
Обращение к невыделенной/освобожденной памяти - это касается и массивов, только там будет неинициализированная память.
Про скорость - уже сказал.
Автор пока явно пишет на C и strcat. С одним массивом это несколько несколько легче, чем с миллионом его элементов.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042786
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CСмотря какая задача. Непосредственно в этом месте:
1. для статического: 100нс латентности + (1000000 элементов * 150 байт / 40 ГБ/c) = 100 + 4000000 = 4 мс.
2. для динамеческого: 100нс * 1000000 э + (1000000 элементов * 150 байт / 40 ГБ/c) = 104 мс.

Так я и сказал, что для этой конкретной задачи никакого выигрыша не будет.
Я не про все задачи говорил.

В большинстве задач, выборка такого размера означает работу с файлом или БД.
И там операции с таким кол-вом элементов имеют существенно большее время, чем сотни мс, да и применяются совсем другие принципы хранения данных чем линейный массив в памяти.
Вообще наиболее вероятные классы задач где надо оптимизировать доступ к куче - это вычисление матриц и низкоуровневые библиотеки управления ппамятью.
Во всех остальных случаях - такая оптимизация скорее всего бессмысленна.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042794
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНа чистом CСмотря какая задача. Непосредственно в этом месте:
1. для статического: 100нс латентности + (1000000 элементов * 150 байт / 40 ГБ/c) = 100 + 4000000 = 4 мс.
2. для динамеческого: 100нс * 1000000 э + (1000000 элементов * 150 байт / 40 ГБ/c) = 104 мс.

Так я и сказал, что для этой конкретной задачи никакого выигрыша не будет.
Я не про все задачи говорил.

В большинстве задач, выборка такого размера означает работу с файлом или БД.
И там операции с таким кол-вом элементов имеют существенно большее время, чем сотни мс, да и применяются совсем другие принципы хранения данных чем линейный массив в памяти.
Вообще наиболее вероятные классы задач где надо оптимизировать доступ к куче - это вычисление матриц и низкоуровневые библиотеки управления ппамятью.
Во всех остальных случаях - такая оптимизация скорее всего бессмысленна.
Ничего себе не будет, 100% * 104/4 = 2600%, в 26 раз:)
Считайте, что СУБД закэшировала эти 150 МБ данных ;)
Там где нужен обход большого количества элементов, а это аналитика, применяют блоки/страницы БД размером порядка 1 МБ, выделенный одним куском в памяти, но уж точно не выделяют память на каждый элемент по 20-50 байт.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042810
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CНичего себе не будет, 100% * 104/4 = 2600%, в 26 раз:)

Реальных задач где вы будете иметь такой выигрыш - нет.
В жизни все сложнее.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042948
пролетевший
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати, использование функций strcpy, strcat, sprintf в C/C++ очень не рекомендуется. Для ядра Linux даже писали утилиту которая находит все случаи использованоя, чтобы удалить.
всегда пользуйтесь версиями с буквой 'n' в середине, для контроля размеров.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38042962
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CПрефетчем можно будет достать в L3/L2 весь массив структур, а в случае с динамической вытащим только указатели, а каждый элемент - 300 тактов задержки на обращение к RAM.
Использование чистого C, как бы намекает на необходимость в скорости.
Оптимизировать все подряд конечно не надо, но использование статического массива, вместо динамического - это и быстрее, и удобней без необходимости выделения, освобождения и проверки на NULL перед использованием.

А почему 300 тактов?
Ведь за один раз сразу будем получать одну структуру, не по одному же элементу будем тянуть.
То есть, выигрыш представляется в три раза. Не три структуры за один раз, а только одну.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043094
На чистом C
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YathaНа чистом CПрефетчем можно будет достать в L3/L2 весь массив структур, а в случае с динамической вытащим только указатели, а каждый элемент - 300 тактов задержки на обращение к RAM.
Использование чистого C, как бы намекает на необходимость в скорости.
Оптимизировать все подряд конечно не надо, но использование статического массива, вместо динамического - это и быстрее, и удобней без необходимости выделения, освобождения и проверки на NULL перед использованием.

А почему 300 тактов?
Ведь за один раз сразу будем получать одну структуру, не по одному же элементу будем тянуть.
То есть, выигрыш представляется в три раза. Не три структуры за один раз, а только одну.
У Anatoly Moskovsky память выделяется под каждый элемент, а не под структуру.

Во-первых с префетчем структуры будем получать сразу все 1000000 в обоих случаях.
Во-вторых с динамическим выделением памяти под каждый элемент , в структуре хранятся только указатели , и за каждым элементом будем обращаться в кучу отдельно.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043126
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом C,

Давайте перестанем теоретизировать и померяемся померяем время работы в обоих случаях для какой-нибудь операции над массивом.
Например возьмем самое простое создание, заполнение и удаление массива.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
#include <iostream>
#include <boost/date_time.hpp>

using namespace std;

struct S1
{
    char movieName[50];
    char producer[50];
    char compString[50];
    void set_fields(const char* movieName, const char* producer)
    {
        strcpy(this->movieName, movieName);
        strcpy(this->producer, producer);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};

struct S2
{
    char* movieName;
    char* producer;
    char* compString;
    S2(): movieName(0), producer(0), compString(0) {}
    ~S2()
    {
        if (movieName) free(movieName);
        if (producer) free(producer);
        if (compString) free(compString);
    }

    void set_fields(const char* movieName, const char* producer)
    {
        this->movieName = strdup(movieName);
        this->producer = strdup(producer);

        this->compString = (char*)malloc(strlen(movieName) + strlen("/") + strlen(producer) + 1);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};

template <class S> void run_test()
{
    const size_t N = 1000000;
    boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time();
    S* v = new S[N];
    for (size_t i = 0; i != N; ++i) {
        char tmp1[50];
        char tmp2[50];
        sprintf(tmp1, "film name %lu", i);
        sprintf(tmp2, "producer %lu", i);
        v[i].set_fields(tmp1, tmp2);
    }
    delete [] v;
    boost::posix_time::ptime t2 = boost::posix_time::microsec_clock::universal_time();
    cout << typeid(S).name() << ": " << (t2 - t1) << endl;
}

int main()
{
    for (size_t i = 0; i != 2; ++i) {
        run_test<S1>();
        run_test<S2>();
    }
    return 0;
}



результат2S1: 00:00:00.498765
2S2: 00:00:00.714403
2S1: 00:00:00.556077
2S2: 00:00:00.791637
(CPU Intel Core I3 330M)

Мы видим что никаких 36 раз нет.
И это я взял только самое примитивное. Разница видна только потому что sprintf сравним по времения с созданием и копированием одной записи.
А как только добавится какая-то нетривиальная обработка каждой записи (например если вы будете фетчить записи из курсора БД), то разница уже будет неощутима .
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043189
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА как только добавится какая-то нетривиальная обработка каждой записи (например если вы будете фетчить записи из курсора БД), то разница уже будет неощутима .
В случае S1 данные уже в формате хранения на диске. Достаточно сделать mmap файла и все данные доступны. в случае S2 их нужно каким то образом загружать.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043225
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OoCcВ случае S1 данные уже в формате хранения на диске. Достаточно сделать mmap файла и все данные доступны. в случае S2 их нужно каким то образом загружать.
Ну я ж просил, без сферических массивов в вакууме.
Посчитайте сколько по времени займет загрузка с диска в память 150МБ файла .
И потом посчитайте, сколько сколько из 150 байтов на запись в среднем будет использовано на полезные данные.
И потом подумайте чей вклад в скорость будет выше - доступа к диску или к памяти.

Проблема в том что тут предлагается рассматривать скорость отдельных низкоуровневых операций, а надо рассматривать скорость алгоритма в целом.
Можно построить быстрый алгоритм на медленных операциях, а можно медленный - на быстрых.
Кроме того, до какого-то значения задержек скорость может быть вообще не важна (если юзер не замечает задержек).
Поэтому не зная алгоритма закладывать в структуры данных существенные ограничения в целях мифической оптимизации - бессмысленно, и даже вредно.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043383
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky,

согласен, все сильно зависит от конкретной задачи. возвращаясь к вашему тесту. поведение аллокатора памяти разное в процессе с одной нитью и несколькими.
прогоните ваш тест как нибудь так

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int main()
{
    for (size_t i = 0; i != 2; ++i) {
            std::thread t1(run_test<S1>);
            t1.join();
            std::thread t2(run_test<S2>);
            t2.join();
        }
    return 0;
}


и результат будет несколько другой.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043441
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovskyрезультат2S1: 00:00:00.498765
2S2: 00:00:00.714403
2S1: 00:00:00.556077
2S2: 00:00:00.791637
(CPU Intel Core I3 330M)

Мы видим что никаких 36 раз нет.
И это я взял только самое примитивное. Разница видна только потому что sprintf сравним по времения с созданием и копированием одной записи.
А как только добавится какая-то нетривиальная обработка каждой записи (например если вы будете фетчить записи из курсора БД), то разница уже будет неощутима .
В тесте не учитывается возможность многопоточной работы и фрагментации памяти. Ясно, что у вас в куче они разложились последовательно и моментально закэшировались.

Создал консольный проект в MSVS 2010:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
// StaticVSDynamicMem.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include <iostream>
#include <boost/date_time.hpp>

using namespace std;

struct S1
{
    char movieName[50];
    char producer[50];
    char compString[50];
    void set_fields(const char* movieName, const char* producer)
    {
        strcpy(this->movieName, movieName);
        strcpy(this->producer, producer);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};

struct S2
{
    char* movieName;
    char* producer;
    char* compString;
    S2(): movieName(0), producer(0), compString(0) {}
    ~S2()
    {
        if (movieName) free(movieName);
        if (producer) free(producer);
        if (compString) free(compString);
    }

    void set_fields(const char* movieName, const char* producer)
    {
        this->movieName = strdup(movieName);
        this->producer = strdup(producer);

        this->compString = (char*)malloc(strlen(movieName) + strlen("/") + strlen(producer) + 1);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};

template <class S> void run_test()
{
    const size_t N = 1000000;
    boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time();
    S* v = new S[N];
    for (size_t i = 0; i != N; ++i) {
        char tmp1[50];
        char tmp2[50];
        sprintf(tmp1, "film name %lu", i);
        sprintf(tmp2, "producer %lu", i);
        v[i].set_fields(tmp1, tmp2);
    }
    delete [] v;
    boost::posix_time::ptime t2 = boost::posix_time::microsec_clock::universal_time();
    cout << typeid(S).name() << ": " << (t2 - t1) << endl;
}

int _tmain()
{
    for (size_t i = 0; i != 2; ++i) {
        run_test<S1>();
        run_test<S2>();
    }

		int a;
		cin >> a;
    return 0;
}



авторstruct S1: 00:00:00.992057
struct S2: 00:01:04.066665
struct S1: 00:00:01.001057
struct S2: 00:01:04.163670
(CPU Intel Core I5 K750)

В 64 раза. И это без учета фрагментации.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043464
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Убрал бустовый замер и оставил clock();. Сделал фрагментацию прыгая с шагом 10000 объектов = 1.5 МБ.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
// StaticVSDynamicMem.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include <ctime>
#include <climits>
#include <iostream>
#include <typeinfo>
#include <stdio.h>
#include <string.h>
 
using namespace std;
 
struct S1
{
    char movieName[50];
    char producer[50];
    char compString[50];
    void set_fields(const char* movieName, const char* producer)
    {
        strcpy(this->movieName, movieName);
        strcpy(this->producer, producer);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
struct S2
{
    char* movieName;
    char* producer;
    char* compString;
    S2(): movieName(0), producer(0), compString(0) {}
    ~S2()
    {
        if (movieName) free(movieName);
        if (producer) free(producer);
        if (compString) free(compString);
    }
 
    void set_fields(const char* movieName, const char* producer)
    {
        this->movieName = strdup(movieName);
        this->producer = strdup(producer);
 
        this->compString = (char*)malloc(strlen(movieName) + strlen("/") + strlen(producer) + 1);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
template <class S> void run_test()
{
    const size_t N = 1000000;
    const size_t step = 10000;
    clock_t t1, t2;
    t1 = clock();
    S* v = new S[N];
 
    for (size_t k = 0; k != step; ++k) {
        for (size_t i = 0; i < N-step; i+=step) {
            char tmp1[50];
            char tmp2[50];
            //strcpy(tmp1, "film name");
            //strcpy(tmp2, "producer");
            sprintf(tmp1, "film name %lu", i);
            sprintf(tmp2, "producer %lu", i);
            v[i + k].set_fields(tmp1, tmp2);
        }
    }
    delete [] v;
    t2 = clock();
    cout << typeid(S).name() << ": " << (t2 - t1) << endl;
}

int _tmain()
{
    for (size_t i = 0; i != 2; ++i) {
        run_test<S1>();
        run_test<S2>();
    }

		int a;
		cin >> a;
    return 0;
}



заполнение через тормозной sprintf:
авторstruct S1: 1026
struct S2: 172125
struct S1: 1024
struct S2: 173539


В 173 раза.

заполнение через быстрый strcpy:
авторstruct S1: 139
struct S2: 125346
struct S1: 137
struct S2: 128770

В 920 раз. Вот это с фрагментацией и видимо многопоточным вариантом malloc/new.

Плюс оверхед на динамической памяти на каждый элемент: 8 байт на указатель + 8 байт на размер + сколько-то в среднем на вырванивание. В сумме 20 байт оверхеда минимум на каждый элемент, плюс 20 байт допустим в среднем строка, итого 40 против 50 - вот и вся экономия :)
Если строка в срденем не 20, а 10, то и в статическом делаем не 50, а 25 и даже выигрываем.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043479
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Microsoft Visual Studio 2010
Версия 10.0.40219.1 SP1Rel
Microsoft Visual C++ 2010
Выставлено: Maximize Speed (/O2)
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043498
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++Microsoft Visual Studio 2010
Версия 10.0.40219.1 SP1Rel
Microsoft Visual C++ 2010
Выставлено: Maximize Speed (/O2)
вот и пользуйся после таких результатов виндой. теперь понятно почему C# такой тормозной.


$ uname -s -r
Linux 3.6.6-1.fc17.x86_64
$ cat /proc/cpuinfo | grep "model name"
model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz
model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz
$ g++ --version
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)

no optimization

strcpy :
автор2S1: 200381 microseconds
2S2: 602437 microseconds
2S1: 495252 microseconds
2S2: 856197 microseconds

sprintf :
автор2S1: 712078 microseconds
2S2: 1114774 microseconds
2S1: 1108407 microseconds
2S2: 1458388 microseconds

threaded
strcpy
автор2S1: 207335 microseconds
2S2: 908294 microseconds
2S1: 511827 microseconds
2S2: 1142337 microseconds

sprintf
автор2S1: 706403 microseconds
2S2: 1420363 microseconds
2S1: 1146519 microseconds
2S2: 1737317 microseconds

итого 1.3 - 4.5 раза разница.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38043511
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если у кого-то под рукой сейчас есть Windows Server 2008 R2 проверьте на ней. Или на FreeBSD, AIX.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044054
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++Microsoft Visual Studio 2010
Версия 10.0.40219.1 SP1Rel
Microsoft Visual C++ 2010
Выставлено: Maximize Speed (/O2)
/O2 - это не все опции.
Давайте сюда всю ком. строку компилятора и линкера.
Я лично не верю в такую разницу между gcc и vs по скорости кода.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044072
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++В тесте не учитывается возможность многопоточной работы и фрагментации памяти. Ясно, что у вас в куче они разложились последовательно и моментально закэшировались.

Да все там учитывалось.
Вы же не думаете, что если у вас в процессе страницы расположены рядом, то и физически они тоже рядом.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044144
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНа C/C++В тесте не учитывается возможность многопоточной работы и фрагментации памяти. Ясно, что у вас в куче они разложились последовательно и моментально закэшировались.

Да все там учитывалось.
Вы же не думаете, что если у вас в процессе страницы расположены рядом, то и физически они тоже рядом.
Я же привел тест в котором явно учитывалась фрагментация и там уже не 64 раза, а 173.


компилятор/Zi /nologo /W3 /WX- /MP /O2 /Oi /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Yu"StdAfx.h" /Fp"Release\StaticVSDynamicMem.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue

линкер/OUT:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.exe" /INCREMENTAL:NO /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Release\StaticVSDynamicMem.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /PGD:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044175
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++Anatoly Moskovskyпропущено...

Да все там учитывалось.
Вы же не думаете, что если у вас в процессе страницы расположены рядом, то и физически они тоже рядом.
Я же привел тест в котором явно учитывалась фрагментация и там уже не 64 раза, а 173.

Ну так у меня на GCC под линуксом ваш тест дает совсем другие цифры что у вас.
2S1: 690000
2S2: 890000
2S1: 960000
2S2: 1170000

Нет даже разницы в разы, не говоря уже про десятки и сотни.

компилятор/Zi /nologo /W3 /WX- /MP /O2 /Oi /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Yu"StdAfx.h" /Fp"Release\StaticVSDynamicMem.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" /Gd /analyze- /errorReport:queue

линкер/OUT:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.exe" /INCREMENTAL:NO /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Release\StaticVSDynamicMem.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.pdb" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /PGD:"C:\VSProject\StaticVSDynamicMem\Release\StaticVSDynamicMem.pgd" /LTCG /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
На первый взгляд все ок.
Будем ждать кого-то с виндой чтобы проверить.
(У меня винда только на виртуалках)
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044180
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, счас только обратил внимание - у вас генерируется код под 32 бита, а у меня 64.
Но все равно это не объясняет такую разницу.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044502
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
#include <ctime>
#include <climits>
#include <iostream>
#include <typeinfo>
#include <stdio.h>
#include <string.h>
 
using namespace std;
 
struct S1
{
    char movieName[50];
    char producer[50];
    char compString[50];
    void set_fields(const char* movieName, const char* producer)
    {
        strcpy(this->movieName, movieName);
        strcpy(this->producer, producer);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
struct S2
{
    char* movieName;
    char* producer;
    char* compString;
    S2(): movieName(0), producer(0), compString(0) {}
    ~S2()
    {
        if (movieName) free(movieName);
        if (producer) free(producer);
        if (compString) free(compString);
    }
 
    void set_fields(const char* movieName, const char* producer)
    {
        this->movieName = strdup(movieName);
        this->producer = strdup(producer);
 
        this->compString = (char*)malloc(strlen(movieName) + strlen("/") + strlen(producer) + 1);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
template <class S> void run_test()
{
    const size_t N = 1000000;
    const size_t step = 10000;
    clock_t t1, t2;
    t1 = clock();
    S* v = new S[N];
 
    for (size_t k = 0; k != step; ++k) {
        for (size_t i = 0; i < N-step; i+=step) {
            char tmp1[50];
            char tmp2[50];
            //strcpy(tmp1, "film name");
            //strcpy(tmp2, "producer");
            sprintf(tmp1, "film name %lu", i);
            sprintf(tmp2, "producer %lu", i);
            v[i + k].set_fields(tmp1, tmp2);
        }
    }
    delete [] v;
    t2 = clock();
    cout << typeid(S).name() << ": " << (t2 - t1) << endl;
}

int main()
{
    for (size_t i = 0; i != 2; ++i) {
        run_test<S1>();
        run_test<S2>();
    }
    return 0;
}

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
set CL=/nologo /O2 /GL
set LINK=/nologo /LTCG /LARGEADDRESSAWARE /SWAPRUN:CD /SWAPRUN:NET
cl /MD /EHsc test
test
struct S1: 1171
struct S2: 2266
struct S1: 1171
struct S2: 4719

MS VS Express 2010 C++
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044514
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. Sidorov+
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
#include <ctime>
#include <climits>
#include <iostream>
#include <typeinfo>
#include <stdio.h>
#include <string.h>
 
using namespace std;
 
struct S1
{
    char movieName[50];
    char producer[50];
    char compString[50];
    void set_fields(const char* movieName, const char* producer)
    {
        strcpy(this->movieName, movieName);
        strcpy(this->producer, producer);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
struct S2
{
    char* movieName;
    char* producer;
    char* compString;
    S2(): movieName(0), producer(0), compString(0) {}
    ~S2()
    {
        if (movieName) free(movieName);
        if (producer) free(producer);
        if (compString) free(compString);
    }
 
    void set_fields(const char* movieName, const char* producer)
    {
        this->movieName = strdup(movieName);
        this->producer = strdup(producer);
 
        this->compString = (char*)malloc(strlen(movieName) + strlen("/") + strlen(producer) + 1);
        strcpy(this->compString, movieName);
        strcat(this->compString, "/");
        strcat(this->compString, producer);
    }
};
 
template <class S> void run_test()
{
    const size_t N = 1000000;
    const size_t step = 10000;
    clock_t t1, t2;
    t1 = clock();
    S* v = new S[N];
 
    for (size_t k = 0; k != step; ++k) {
        for (size_t i = 0; i < N-step; i+=step) {
            char tmp1[50];
            char tmp2[50];
            //strcpy(tmp1, "film name");
            //strcpy(tmp2, "producer");
            sprintf(tmp1, "film name %lu", i);
            sprintf(tmp2, "producer %lu", i);
            v[i + k].set_fields(tmp1, tmp2);
        }
    }
    delete [] v;
    t2 = clock();
    cout << typeid(S).name() << ": " << (t2 - t1) << endl;
}

int main()
{
    for (size_t i = 0; i != 2; ++i) {
        run_test<S1>();
        run_test<S2>();
    }
    return 0;
}

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
set CL=/nologo /O2 /GL
set LINK=/nologo /LTCG /LARGEADDRESSAWARE /SWAPRUN:CD /SWAPRUN:NET
cl /MD /EHsc test
test
struct S1: 1171
struct S2: 2266
struct S1: 1171
struct S2: 4719

MS VS Express 2010 C++
А какая винда, Win7x64?
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044520
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++А какая винда, Win7x64?Windows Server 2003 x64 R2 SP2.

P.S. Насколько я понял гугла, stdafx - предкомпилированные хедеры и прочая для уменьшения времени сборки (большого) проекта.
Если даже не задаваться вопросом: "Азадлянафига всё это для цатистрочного исходника-пузомерки?", то уменьшение времени сборки и оптимальная кодогенерация - не просто попиндикулярны, а прямо противоположны.
"Как-то так" (ц) Винни-Пух.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044689
На C/C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovНа C/C++А какая винда, Win7x64?Windows Server 2003 x64 R2 SP2.

P.S. Насколько я понял гугла, stdafx - предкомпилированные хедеры и прочая для уменьшения времени сборки (большого) проекта.
Если даже не задаваться вопросом: "Азадлянафига всё это для цатистрочного исходника-пузомерки?", то уменьшение времени сборки и оптимальная кодогенерация - не просто попиндикулярны, а прямо противоположны.
"Как-то так" (ц) Винни-Пух.
Пробовал и без предкомилированных stdafx и скомпилить x64, тоже самое.
Видите, Windows Server 2003 x64 R2 всего в 2-5 раз, а Win7x64 в сотни раз.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38044807
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На чистом CYathaпропущено...


А почему 300 тактов?
Ведь за один раз сразу будем получать одну структуру, не по одному же элементу будем тянуть.
То есть, выигрыш представляется в три раза. Не три структуры за один раз, а только одну.
У Anatoly Moskovsky память выделяется под каждый элемент, а не под структуру.

Во-первых с префетчем структуры будем получать сразу все 1000000 в обоих случаях.
Во-вторых с динамическим выделением памяти под каждый элемент , в структуре хранятся только указатели , и за каждым элементом будем обращаться в кучу отдельно.

Согласен, что статический массив будет быстрее динамического. Но в учебных примерах любят выделять и освобождать память, аргументируя тем, что значение может не поместиться, да и память надо экономить. Хотя с восьмибайтовыми указателями экономия, действительно, неочевидна.
...
Рейтинг: 0 / 0
strcat - ошибка
    #38045784
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На C/C++Пробовал и без предкомилированных stdafx и скомпилить x64, тоже самое.
Видите, Windows Server 2003 x64 R2 всего в 2-5 раз, а Win7x64 в сотни раз.Т.к. в VSExpress "недоклали" x64-версии компиляторов/SDK, а вынимать необходимый минимум из "большой студии" было лень - я собирал x86-версию.

P.S. Попробуйте, всё-таки, собрать в комстроке именно с такими переменными среды и опциями компилятора.
LargeAddressAware и SwapRun - можно опустить, /arch:SSE2 - добавить :)
...
Рейтинг: 0 / 0
62 сообщений из 62, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / strcat - ошибка
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]