LINUX.ORG.RU

ошибка: нет декларации «strcpy» в этой области видимости


0

1

gcc 4.6.1

В инклудах это:

#include <cstdlib>
#include <iostream>
#include <queue>
#include <string>
#include <pthread.h>

#include <curl/curl.h>
#include <curl/easy.h>

#include "document_struct.h"
#include "html_getting_thread.h"

Как видно, string - на месте, объявление strcpy в заголовочном файле есть, по клику на функцию IDE (NetBeans 7.1) успешно находит ее. При попытке компиляции gcc вываливается с сабжем. Я очень уверен, что где - то неправ именно я, а не компилятор, но разобраться за 4 часа копания в гугле не получилось.

По сути мне нужно const char* скопировать в char*, может есть аналоги? Руками писать - не комельфо как то, знаю что можно через memcpy с проверкой на /0, но блин, костыль же?

P.S.: Эту проблему ув. форумчане помогли решить и она более не актуальна. Нужно подключать cstring:

#include <cstring>

Код:

//Вечный цикл работы потока
    for (;;) {
        //Если пришло время прощаться, значит такова жизнь
        if (itsTimeToSayGoodbye)
            break;

        //Блокировка мьютекса для очереди url
        pthread_mutex_lock(&params->urlsMutex);

        //Если очеред не пуста, выдираем из нее один url 
        //и качаем с него контент
        if (!urls->empty()) {
            //Буффер для принятия данных от curl
            string* dataBuffer = new string();

            string* url = new string(urls->front());
            urls->pop();

            //Незачем более держать доступ к очереди, зарблокируем мьютекс
            pthread_mutex_unlock(&params->urlsMutex);

            char* urlBuff = new char(url->length() + 1);
            strcpy(urlBuff, url->c_str());
            
            //Вылетает с SIGABRT на этом месте <-------
            curl_easy_setopt(curl, CURLOPT_URL, urlBuff);

            curl_easy_setopt(curl, CURLOPT_WRITEDATA, dataBuffer);
            
            CURLcode responseCode;
            responseCode = curl_easy_perform(curl);
            cout << dataBuffer->c_str();
            if(responseCode != CURLE_OK) {
                string* curlErrorMessage = new string(curl_easy_strerror(responseCode));
                
                cout << "==== ATTENTION! ====" << endl;
                cout << "Curl error: " << curlErrorMessage->c_str() << endl << "URL: " << url->c_str() 
                        << endl << "Thread #" << (params->lastThreadIndex - 1)  << endl;
                cout << "====================" << endl;
                
                delete curlErrorMessage;
            }


            //Почистим за собой память, dataBuffer оставим, т.к. в нем
            //у нас данные документа, которые будут переданы парсеру
            curl_easy_setopt(curl, CURLOPT_URL, NULL);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
            delete urlBuff;
            delete url;
        } else {
            //Очередь оказалась пуста, а мы уже заблокировали мьютекс,
            //отпустим его.
            pthread_mutex_unlock(&params->urlsMutex);
        }

        //Пускай процессор подышит, наша задача не самая приоритетная
        sleep(100);
    }



Последнее исправление: Seraph (всего исправлений: 2)

#include <iostream>

У тебя в посте каша из gcc и C++. Рекомендую разобраться перед тем, как продолжишь изучать программирование.

ttnl ★★★★★
()

[code] $ man strcpy

STRCPY(3) Руководство программиста STRCPY(3)

НАЗВАНИЕ strcpy, strncpy - копирование строки

СИНТАКСИС #include <string.h>

char *strcpy(char *dest, const char *src);

[/code]

Внезапно, string.h и string это РАЗНЫЕ хидеры. Соотв. при юзании string.h все собирается и падает за счет Ваших косяков.

AIv ★★★★★
()
Ответ на: комментарий от ttnl

Почему же каша? Я бы мог написать программу на C, но мне необходимы компоненты STL, я привел кусок кода из функции - потока. Да я не использую обертку над curl, если честно мне кажется это лишним, и так все вполне удобно.

Вероятно я не прав в чем - то? Скажите почему мой код показался вам кашей? Я стараюсь вникать в Си++, пока получается так, как вы видите. Возможно ваши рекомендации относительно конкретно этого кода, помогут мне улучшить мой скилл в кодинге.

Seraph
() автор топика

Stdio.h предлагали?

bk_ ★★
()
Ответ на: комментарий от AIv

Вы абсолютно правы, я только сейчас понял, что IDE открывала string.h. Ок! Спасибо что забежали в man вместо меня =)

Вот, что мне удалось узнать(дебаггер помог): strcpy отрабатывает нормально, программа падает на этом:

curl_easy_setopt(curl, CURLOPT_URL, urlBuff);

Вылетает с SIGABRT.

Seraph
() автор топика

string - это плюсовая std, после подключения этого файла достпен класс строки. То, что ты ищешь, находится в cstring по стандарту и в string.h в наследство от сишного компилятора.

staseg ★★★★★
()
Ответ на: комментарий от ttnl

Эм =) Ну да, вы конечно же правы, вероятно я и в этом вопросе не особо шарю, но мне всегда казалось, что gcc - это сборка, а не компилятор, а уже g++ - это один из компонентов gcc. Я не прав?

Seraph
() автор топика
Ответ на: комментарий от staseg

Спасибо, не знал, впредь буду использовать подключение cstring!

Seraph
() автор топика
Ответ на: комментарий от Seraph

Хрен знает, что из них компилятор, а что сборка, не в этом суть. Суть в том, что C++ файлы нужно компилировать с помощью g++

ttnl ★★★★★
()
Ответ на: комментарий от Seraph

Отлично. По остальным вопросам - вопросам объявления функции - лучше всего консультироваться с man. Думаю, половина отвечающих с ним ознакомилась перед ответом. В линуксе - только так

ttnl ★★★★★
()
Ответ на: комментарий от Seraph

Отвечаю сам себе. Разобрался с SIGABRT. Оказывается для нужд curl память нужно выделять через malloc. Пример:

 
//Программа вылетит с SIGABRT если такой указатель 
//передать в качестве CURLOPT_URL 
char* buffer = new char(1024);

//Программа не вылетит с SIGABRT 
char* buffer = (char*) malloc(1024);
 

Лично я всегда думал, что malloc и new - это одно и тоже в контексте C++, какая собственно разница для curl каким образом я выделяю память мне не известно.

Seraph
() автор топика
Ответ на: комментарий от PolarFox

Нет я не плакалЬ... я РЫДАЛЬ! Это пожалуй стоит

for( int i; i++; i<N ){...}

AIv ★★★★★
()
Ответ на: комментарий от PolarFox

Ухты! Вы абсолютно правы, теперь работает через new =) Благодарю!

А что же означали тогда круглые скобки? Что я делал на самом деле этим кодом?

char* buffer = new char(1024);

Seraph
() автор топика
Ответ на: комментарий от Seraph

Не знаю как оно такое реализовано в крестах, но если бы char был бы классом, то это выделение памяти под один экземпляр класса, конструктору которого передаётся число 1024.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Хм, конечно не уверен, но думаю так и есть. Получается я выделял память под один char, который имел значение 1024...

Seraph
() автор топика
Ответ на: комментарий от PolarFox

Подозреваю, что аналогично char инициализировался чиселкой 1024.

ТС-у - вообще есть опция -Wall при сборке... настоятельно рекомендуется ей пользоваться.

AIv ★★★★★
()
Ответ на: комментарий от frozenix

frozenix

new и malloc никогда небыло одним и тем же.

это две разные обёртки одного и того-же. Основное принципиальное значение в том, что malloc() это функция из стандартной либы, а вот new это вообще-то языковая конструкция. Но память они выделяют одну и ту же, из одной кучи, и одним способом. Другое дело, что во время компиляции, компилятор намного больше знает об объекте, который выделен оператором new (например наличие таблицы виртуальных функций, наличие которой вообще говоря может изменится по ходу программы, и если сделать free, то всё посыпется)

frozenix

пиши на питоне.

поставь виндовс7 и иди на винфак.

Seraph, не надо мешать языки С и С++. Они только кажутся похожими. На самом деле, они действительно похожие, только не так, как вы думаете. Суть в том, что С++ это вывернутый на изнанку С. Потому подобные проблемы вас будут преследовать постоянно. Если уж почему-то надо написать какую-то часть именно на чистом C, создайте отдельный файл, и там пишите, но только на С. Кстати, доказано, что на С++ можно сделать тоже самое, что и на С. И тоже самое можно сделать на пайтоне/питоне/sed, короче на любом Тьюринг-полном ЯП. Даже на BrainFuck'e. Какой смысл их мешать? В каждом свои тонкости. Самое опасное - выделение памяти, такие ошибки можно неделями искать, если код корявый.

drBatty ★★
()
Ответ на: комментарий от frozenix

Спасибо конечно за добрый совет, но я воздержусь.

Seraph
() автор топика
Ответ на: комментарий от drBatty

А вы не могли бы поточнее подсказать, что я сделал не так? Т.е. мне интересно в чем заключается смешивание? Код который я привел - это всего лишь участок из функции - потока, но вы уже не первый кто говорит мне что я смешал два языка... собственно где я неправ? =)

Мои примеры насчет new и malloc - это, как бы точнее выразиться, я тыкал пальцем в небо. Собственно совершенно логичное решение я думаю, ведь если libcurl изначально создан для чистого Си то и память логичнее выделять методами из чистого Си.

Seraph
() автор топика
Ответ на: комментарий от Kosyak

По анологии:

cassert (assert.h)
cctype (ctype.h)
cerrno (errno.h)
cfloat (float.h)
ciso646 (iso646.h)
climits (limits.h)
clocale (locale.h)
cmath (math.h)
csetjmp (setjmp.h)
csignal (signal.h)
cstdarg (stdarg.h)
cstddef (stddef.h)
cstdio (stdio.h)
cstdlib (stdlib.h)
cstring (string.h)
ctime (time.h)

Kosyak ★★★★
()
Ответ на: комментарий от Seraph

охереть; ты не знаешь не с не с++, читай стандарт
внезапно, в c нет iostream, это одна из многих лаж в твоём коде

anonymous
()
Ответ на: комментарий от Seraph

Seraph

А вы не могли бы поточнее подсказать, что я сделал не так?

1. как пишется на C? Очень просто - создаём main(), которая вызывает какие-то функции. Эти функции вызывают другие функции, и так далее. Функции в принимают/возвращают переменные, указатели, и структуры (массивы не умеют). Потому разработка по уму должна вестись «с конца», с функции, которые на самом нижнем уровне. В вашем случае нужно создать функцию, которая работает с «резиновыми» строками, т.е. со строками, в которых не ограничен размер. В качестве контейнера можно использовать указатель на структуру, где сама строка, и длинна выделенного буфера. Я понимаю, в string:: это всё уже реализовано, но задача настолько проста, что кода будет меньше, если изобрести велосипед. А так вы тратите много сил на сопряжение C и C++, что не оправданно в таком простом случае.
Затем пишете функцию, которая собственно и юзает curl, и она принимает в качестве параметра указатель на вашу строчку. Затем функцию, которая обрабатывает урлы, и вызывает функцию curl. Ну и её пихаете в main()
профит

Если вы пишете на С++, то всё делаете в том же порядке, но иначе. У вас теперь нет функции для строк, забудьте. Есть класс «строка». B и его методы. Потому мы сразу создаём наш класс, который будет качать что-то там. Он в общем-то состоит из трёх методов:
1. конструктор, который принимает урлы и что надо
2. метода load() который собственно грузит
3. и деструктора, который подчищает мусор.
с первым проблем наверное не будет, проблема со вторым. Ну урлы тут уже не меняются, их можно string::c_str(), а вот новый буфер лучше вернуть(или вернуть NULL, если ошибка. Причём возвращать его надо как const char *, в силу того, что парсеру менять его не нужно. Что до деструктора, то там надо подчистить то, что навызывал конструктор. То, что образовалось внутри методов чистить не нужно.
Вообще, в C++ лучше не использовать new везде, где это только возможно. Если вам нужен один объект x класса X, то просто напишите X x(параметры инициализации). Он тогда сам удалится. Создавать new объекты надо там же, где удаляете. Например буфер придётся создать в конструкторе, и удалить в деструкторе. Переменные вроде url можно описать прямо в классе, и сам класс создавать на стеке. Т.о., оператор new нужен в случаях, когда объект выходит за периметр класса. Тут надо следить, что-бы класс не удалился-бы раньше, чем будет нужен этот объект. Это не проблема, если вызывающий метод никуда не отправляет объект, и его не удаляет вообще, он удалится самостоятельно при выходе из метода. Кроме того, метод new годен для данных, которые большие, и/или размер которых неизвестен. Обычно их удобно инициализировать в конструкторе, и удалять в деструкторе. И да, деструктор должен быть виртуальным, дабы гарантировать правильное удаление всех компонентов (когда вы удаляете объект который суть производный класс, но удаляете таки объект базового, должен выполнится сначала деструктор производного, а потом деструктор базового. Если деструктор не виртуальный, то delete не сможет узнать, что это не базовый класс, а на самом деле производный, ведь тип указателя - базовый).

Ну а main() у нас - единственная функция в программе, которая создаёт класс Main, имеющий один метод «сделайте мне хорошо».

Seraph

Код который я привел - это всего лишь участок из функции - потока, но вы уже не первый кто говорит мне что я смешал два языка...

вы пишете используя парадигму C, а не ООП. При этом вы используете STL и прочие С++ штучки. Кроме того, вы создаёте string'и в куче, а не на стеке. Зачем? string это в С++ такой-же тип как int, вам не приходит в голову писать int* px = new(7); ? Не? А почему?

Seraph

Мои примеры насчет new и malloc - это, как бы точнее выразиться, я тыкал пальцем в небо. Собственно совершенно логичное решение я думаю, ведь если libcurl изначально создан для чистого Си то и память логичнее выделять методами из чистого Си.

не. если вы пишете new char[100], вы получаете указатель на кусок памяти, причём 100 байт этой памяти в полном вашем распоряжении. Делайте с ними что хотите. Как и с malloc(100). Отличия начинаются, когда вы создаёте классы, ибо malloc во первых не вызовет конструкторы, а во вторых, free (и delete) могут ошибиться с размером класса, ну и также не вызовет деструктор. Короче - как используется память - без разницы. А вот как выделяется/удаляется - разница есть.

drBatty ★★
()
Ответ на: комментарий от anonymous

anonymous

охереть; ты не знаешь не с не с++, читай стандарт

охренеть, ну и аноны пошли... Да, ЛОР уже не торт...

1. ТС и не претендует на звание гуру
2. стандарт его ничему не научит. Надо Страуструпа читать, а уж потом - стандарт.

drBatty ★★
()
Ответ на: комментарий от drBatty

Потому мы сразу создаём наш класс, который будет качать что-то там. Он в общем-то состоит из трёх методов: [list type=1]

  • конструктор, который принимает урлы и что надо
  • метода load() который собственно грузит
  • и деструктора, который подчищает мусор.

ООП головного мозга? В таком классе смысла нет, это просто применение средств языка без понимания для чего они предназначены.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Begemoth

ООП головного мозга? В таком классе смысла нет, это просто применение средств языка без понимания для чего они предназначены.

нет конечно. Это каркас, к которому ТС присобачит новые методы. Потом конечно выкинет нафиг всё, и напишет нормально. Я просто хотел показать отличия ООП от простого С.

И да - никто не мешает тебе высказать своё мнение. Как оно нужно делать. Жду...

drBatty ★★
()
Ответ на: комментарий от drBatty

Я просто хотел показать отличия ООП от простого С.

Плохо показал, мне вот совершенно не понятно зачем делать такой класс и чем же он лучше одной функции или набора независимых функций.

И да - никто не мешает тебе высказать своё мнение. Как оно нужно делать. Жду...

1. Шаблон класса очереди сообщений (для начала простейший: без таймаутов на помещение и извелчение в/из очереди, но с условными переменными, а не busy wait).

2. Обёртка над cURL чтобы голые указатели и функции из cstring наружу не торчали, конкретного ничего не скажу, т.к. API CURL не представляю.

3. Функция цикла закачки, использующая 1 и 2, вида

void downloadFromQueue(MessageQueue<DownloadMsg>& queue)
{
   for(;;) {
      auto m = queue.receive();
      if (m.isTerminationRequest()) break;

      downloadURL(m.url());
   }
}

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

Вот и всё.

Begemoth ★★★★★
()
Ответ на: комментарий от drBatty

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

new выделяет из free store, malloc - из кучи. Что не одно и то же.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от drBatty

Так у него вообще практически С. Из плюсов - только delete'ы да cout'ы.

Вот про таких я и говорю: нечего плюсы пихать туда, где голый си нужен.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Eddy_Em

Так у него вообще практически С. Из плюсов - только delete'ы да cout'ы.

нет, все строки он хранит в cstring. ИМХО половину кода. Да и вообще весь кусок в полном соответствии с Сстилем, а почти все «функции» из С++.

Eddy_Em

нечего плюсы пихать туда, где голый си нужен.

да.. это я от недосыпу такую хрень расписал (см. выше). Ну пусть будет.

drBatty ★★
()

В мане написано:

#include <string.h>

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Спасибо! Пожалуйста читайте тред перед тем как писать сообщения, мне уже подсказали, что я ошибся насчет круглых скобок.

Seraph
() автор топика
Ответ на: комментарий от Seraph

Спасибо!

Пожалуйста.

Пожалуйста читайте тред перед тем как писать сообщения, мне уже подсказали, что я ошибся насчет круглых скобок.

И вам спасибо.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.