The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"работа с памятью"
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"работа с памятью"
Сообщение от Vasili emailИскать по авторуВ закладки on 07-Июл-03, 10:16  (MSK)
Есть класс. В его конструкторе делается след.:

char str1 = new char[255];

Далее в main создается экземпляр класса и тут же main завершается вызвав деструктор. В деструкторе проставлено след.: delete []str1;

После этой операции freebsd выкидывает:

billd in free(): warning: junk pointer, too high to make sense

Что я делаю не правильно?

  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 07-Июл-03, 10:38  (MSK)
>Есть класс. В его конструкторе делается след.:
>
>char str1 = new char[255];
>
>Далее в main создается экземпляр класса и тут же main завершается вызвав
>деструктор. В деструкторе проставлено след.: delete []str1;
>
>После этой операции freebsd выкидывает:
>
>billd in free(): warning: junk pointer, too high to make sense
>
>Что я делаю не правильно?

Наверное char str1 локальная переменная в конструкторе
Надо

const int SZ = 512;
try {
str1 = new char[ SZ ];
...
}
catch ( bad_alloc ) {
...
}

или
str1 = new( nothrow ) char[ SZ ];
if ( str1 == 0 ) {
   cerr << "new error\n";
}

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "работа с памятью"
Сообщение от messer Искать по авторуВ закладки on 08-Июл-03, 08:12  (MSK)
как можно выделить 255х1 байт под 1 байт?
char *str1 = new char[255];
  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 08-Июл-03, 09:47  (MSK)
>как можно выделить 255х1 байт под 1 байт?
>char *str1 = new char[255];
  Правильно, опечатка :)

Однако как я уже говорил проблема в том, что скорее всего член класса не инициализирован.  

Дело в том, что если даже и забыть '*' при объявлении указателя нормальный С++ компилятор ВСЕГДА (даже без -Wall) выдаст ПРЕДУПРЕЖДЕНИЕ (что-то вроде: Can not convert char* to char)

В случае со "спрятанной" переменной компилятор ругаться не будет:

#include <iostream>
#include <cassert>

using namespace std;

class C {
char* ptr_;
public:
explicit C( char* p = 0 ) {
char* ptr_ = new(nothrow) char[ strlen( p ) + 1 ];
assert( ptr_ );
strcpy( ptr_, p );
}
~C() throw()
{
delete[] ptr_;
}
};

int main( int argc, char** argv )
{
C c( "AAAAAAAAAA" );
return 0;
}

Если компилить, то будет все нормально, но удалять то мы будем память, которую не выделяли

В любом случае спасибо за замечание. Мне надо быть внимательнее.

Успехов
--- sas

PS Кстати код не был скомпилирован и могут быть еще опечатки  :)

  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 08-Июл-03, 09:58  (MSK)
>>как можно выделить 255х1 байт под 1 байт?
>>char *str1 = new char[255];
>  Правильно, опечатка :)
>
>Однако как я уже говорил проблема в том, что скорее всего член
>класса не инициализирован.
>
>Дело в том, что если даже и забыть '*' при объявлении указателя
>нормальный С++ компилятор ВСЕГДА (даже без -Wall) выдаст ПРЕДУПРЕЖДЕНИЕ (что-то вроде:
>Can not convert char* to char)
>
>В случае со "спрятанной" переменной компилятор ругаться не будет:
>
>#include <iostream>
>#include <cassert>
>
>using namespace std;
>
>class C {
> char* ptr_;
>public:
> explicit C( char* p = 0 ) {
>  char* ptr_ = new(nothrow) char[ strlen( p ) + 1
>];
>  assert( ptr_ );
>  strcpy( ptr_, p );
> }
> ~C() throw()
> {
>  delete[] ptr_;
> }
>};
>
>int main( int argc, char** argv )
>{
> C c( "AAAAAAAAAA" );
> return 0;
>}
>
>Если компилить, то будет все нормально, но удалять то мы будем память,
>которую не выделяли
>
>В любом случае спасибо за замечание. Мне надо быть внимательнее.
>
>Успехов
>--- sas
>
>PS Кстати код не был скомпилирован и могут быть еще опечатки  
>:)


А вот и опечатка   :))
правильнее:

explicit C( const  char* p = "" ) {

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "работа с памятью"
Сообщение от messer Искать по авторуВ закладки on 09-Июл-03, 08:23  (MSK)
>>как можно выделить 255х1 байт под 1 байт?
>>char *str1 = new char[255];
>  Правильно, опечатка :)
>
>Однако как я уже говорил проблема в том, что скорее всего член
>класса не инициализирован.

согласен. чтобы избежать ошибки нужно просто инициализировать указатель NULL'ом.
>
>Дело в том, что если даже и забыть '*' при объявлении указателя
>нормальный С++ компилятор ВСЕГДА (даже без -Wall) выдаст ПРЕДУПРЕЖДЕНИЕ (что-то вроде:
>Can not convert char* to char)
>
>В случае со "спрятанной" переменной компилятор ругаться не будет:
>
>#include <iostream>
>#include <cassert>
>
>using namespace std;
>
>class C {
> char* ptr_;
>public:
> explicit C( char* p = 0 ) {
>  char* ptr_ = new(nothrow) char[ strlen( p ) + 1
>];
>  assert( ptr_ );
>  strcpy( ptr_, p );
> }
> ~C() throw()
> {
>  delete[] ptr_;
> }
>};
>

Один маленький изъян в исходнике :) Если конструктор будет вызван без параметров, будет выделен один байт памяти, в который будем помещен нулевой байт (хотя возможно '\0' и не будет помещен в этот выделенный байт - нет перед глазами исходника strcpy()). Поэтому первой строчкой конструктора можно написать:
if (!strlen(p)) return;

>int main( int argc, char** argv )
>{
> C c( "AAAAAAAAAA" );
> return 0;
>}
>
>Если компилить, то будет все нормально, но удалять то мы будем память,
>которую не выделяли
>
>В любом случае спасибо за замечание. Мне надо быть внимательнее.
>
>Успехов
>--- sas
>
>PS Кстати код не был скомпилирован и могут быть еще опечатки  
>:)


  Рекомендовать в FAQ | Cообщить модератору | Наверх

9. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 09-Июл-03, 09:46  (MSK)
>>>как можно выделить 255х1 байт под 1 байт?
>>>char *str1 = new char[255];
>>  Правильно, опечатка :)
>>
>>Однако как я уже говорил проблема в том, что скорее всего член
>>класса не инициализирован.
>
>согласен. чтобы избежать ошибки нужно просто инициализировать указатель NULL'ом.
>>
>>Дело в том, что если даже и забыть '*' при объявлении указателя
>>нормальный С++ компилятор ВСЕГДА (даже без -Wall) выдаст ПРЕДУПРЕЖДЕНИЕ (что-то вроде:
>>Can not convert char* to char)
>>
>>В случае со "спрятанной" переменной компилятор ругаться не будет:
>>
>>#include <iostream>
>>#include <cassert>
>>
>>using namespace std;
>>
>>class C {
>> char* ptr_;
>>public:
>> explicit C( char* p = 0 ) {
>>  char* ptr_ = new(nothrow) char[ strlen( p ) + 1
>>];
>>  assert( ptr_ );
>>  strcpy( ptr_, p );
>> }
>> ~C() throw()
>> {
>>  delete[] ptr_;
>> }
>>};
>>
>
>Один маленький изъян в исходнике :) Если конструктор будет вызван без параметров,
>будет выделен один байт памяти, в который будем помещен нулевой байт
>(хотя возможно '\0' и не будет помещен в этот выделенный байт
>- нет перед глазами исходника strcpy()). Поэтому первой строчкой конструктора можно
>написать:
>if (!strlen(p)) return;

man strcpy

The strcpy() function copies the string src to dst (including the terminating `\0' character).

В нашем случае вся src строка == '\0' т.е. все будет нормально.

А вот при Вашем варианте возможен core dump

explicit C( const char* p = 0 ) {  // или C( const char* = "" )
     if ( strlen( p ) == 0 ) return;
     try {
     ptr_ = new char[ strlen( p ) + 1 ];
     ...
}

Что получаем?

Вошли в конструктор и выскочили без инициализации ptr_. Если объект типа С не статический, то  ptr_ == мусору (те указывает непонятно куда)

Попали в деструктор и пытаемся удалить непонятно что   :(

Точно таже проблема, что и вызвала к жизни это обсуждение, только у первого постера локальная переменная конструктора маскировала член класса и он не был проинициализирован

>
>>int main( int argc, char** argv )
>>{
>> C c( "AAAAAAAAAA" );
>> return 0;
>>}
>>
>>Если компилить, то будет все нормально, но удалять то мы будем память,
>>которую не выделяли
>>
>>В любом случае спасибо за замечание. Мне надо быть внимательнее.
>>
>>Успехов
>>--- sas
>>
>>PS Кстати код не был скомпилирован и могут быть еще опечатки  
>>:)

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

14. "работа с памятью"
Сообщение от messer Искать по авторуВ закладки on 10-Июл-03, 07:00  (MSK)
>>>>как можно выделить 255х1 байт под 1 байт?
>>>>char *str1 = new char[255];
>>Один маленький изъян в исходнике :) Если конструктор будет вызван без параметров,
>>будет выделен один байт памяти, в который будем помещен нулевой байт
>>(хотя возможно '\0' и не будет помещен в этот выделенный байт
>>- нет перед глазами исходника strcpy()). Поэтому первой строчкой конструктора можно
>>написать:
>>if (!strlen(p)) return;
>
>man strcpy
>
>The strcpy() function copies the string src to dst (including the terminating
>`\0' character).
>
>В нашем случае вся src строка == '\0' т.е. все будет нормально.
>
>
>А вот при Вашем варианте возможен core dump
>
>explicit C( const char* p = 0 ) {  // или
>C( const char* = "" )
>     if ( strlen( p ) == 0
>) return;
>     try {
>     ptr_ = new char[ strlen( p )
>+ 1 ];
>     ...
>}
>
>Что получаем?
>
>Вошли в конструктор и выскочили без инициализации ptr_. Если объект типа С
>не статический, то  ptr_ == мусору (те указывает непонятно куда)
>
>
>Попали в деструктор и пытаемся удалить непонятно что   :(
>
>Точно таже проблема, что и вызвала к жизни это обсуждение, только у
>первого постера локальная переменная конструктора маскировала член класса и он не
>был проинициализирован
>

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

  Рекомендовать в FAQ | Cообщить модератору | Наверх

15. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 10-Июл-03, 08:54  (MSK)
>Я писал применительно к к Вашему коду, демонстрирующему ошибку. А так естественно
>нужно первой строкой инициализировать указатель, а потом проверять длинну строки. Я
>просто хотел, что в Вашем коде при нулевой длинне строки выделяется
>один байт, когда этого можно не делать.

1) Мой  код написан для иллюстрации проблемы, задавшего вопрос (ОН НЕ ПРЕТЕНДУЕТ НА ПРАВИЛЬНОСТЬ ИЛИ КРАСИВОСТЬ):

class C {
        char*        ptr_;
public:
        explicit C( char* p = 0 ) {
                char* ptr_ = new(nothrow) char[ strlen( p ) + 1 ];
                ======

ЛОКАЛЬНАЯ ПЕРЕМЕННАЯ В КОНСТРУКТОРЕ МАСКИРУЕТ ЧЛЕН КЛАССА
                                                                      ========

2) Если переменная проинициализирована, то и проблемы нет (см пункт 1).

3) Ниже точное копия Вашего ответа:

>>>Один маленький изъян в исходнике :) Если конструктор будет вызван без параметров,
>>>будет выделен один байт памяти, в который будем помещен нулевой байт
>>>(хотя возможно '\0' и не будет помещен в этот выделенный байт
>>>- нет перед глазами исходника strcpy()). Поэтому первой строчкой конструктора можно
>>>написать:
>>>if (!strlen(p)) return;

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

explicit C( const char* p = "" ) : ptr_( 0 )

только предотвратит core dump, но вопрос с МАСКИРОВКОЙ не решит

4) А теперь полностью off-topic к этому обсуждению:

class C {
      string s_;
public:
      explicit C( const char* p = "" ) : s_( p ) {}
      ~C() {}
};
  
Кстати это наиболее правильный код в стиле С++

При этом решении в случае

C c( 0 );

может быть core dump (см пункт 5 ниже)

5) Кстати я ТОЖЕ СМОЛОЛ ЧУШЬ когда сказал, что const char* p = 0 то же самое, что
const char* p = ""  

Указатель на 0 - это не пустая строка, поэтому strcpy( s, 0 ) == core dump скорее всего

Прошу прощения за неправильную фразу в предидущем посте

Единственное что меня извиняет НЕМНОГО это следующий пост после примера (до Вашего поста с предложением о проверке с помощью strlen)

========================================
            Сообщение от sas   on        08-Июл-03, 09:58  (MSK)          
...

А вот и опечатка   :))
правильнее:

        explicit C( const  char* p = "" ) {
=========================================

:)

6) Что хорошо с 0 передаваемым в функции/конструкторы/методы и т.д. - это что
найти ошибку сравнительно легко. Программа упадет при обращении к 0 всегда, в отличии от диких (непроинициализированных) указателей. Ошибки с ними отловить НА ПОРЯДОК труднее

Спасибо
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 08-Июл-03, 10:22  (MSK)
>как можно выделить 255х1 байт под 1 байт?
>char *str1 = new char[255];

Кстати, перечитав свой и Ваш ответы, я заметил, что Вы неправильно выразили свою мысль:

Дело в том, что new возвращает указатель (на i386 это long (если не ошибаюсь)) Так что при записи

char ptr_ = new char[ SZ ];

из-за разницы в размерах происходит потеря (truncate) 3-х старших байт. И совершенно не важно чему равен SZ (хоть 10000)

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

Именно из-за такого типа проблем компилятор всегда будет ругаться

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "работа с памятью"
Сообщение от messer Искать по авторуВ закладки on 09-Июл-03, 08:40  (MSK)
>>как можно выделить 255х1 байт под 1 байт?
>>char *str1 = new char[255];
>
>Кстати, перечитав свой и Ваш ответы, я заметил, что Вы неправильно выразили

Разве может описание неверного куска кода быть технически верным? В левой части стоял не указатель, поэтому я и написал о выделении 255 байт под один.

>свою мысль:
>
>Дело в том, что new возвращает указатель (на i386 это long (если
>не ошибаюсь)) Так что при записи
>
>char ptr_ = new char[ SZ ];
>
>из-за разницы в размерах происходит потеря (truncate) 3-х старших байт. И совершенно
>не важно чему равен SZ (хоть 10000)

Естественно оператор new возвращает 4-байтный (на i386) адрес начала выделенной области памяти от SZ не зависящий -))

>
>Конечно в любом случае это ошибка (вероятность того, что значение указателя не
>было при этом искажено очеееееееень мала), но надо понимать, что происходит
>"за кадром"
>
>Именно из-за такого типа проблем компилятор всегда будет ругаться
>
>Успехов
>--- sas


  Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 09-Июл-03, 09:32  (MSK)
>>>как можно выделить 255х1 байт под 1 байт?
>>>char *str1 = new char[255];
>>
>>Кстати, перечитав свой и Ваш ответы, я заметил, что Вы неправильно выразили
>
>Разве может описание неверного куска кода быть технически верным? В левой части
>стоял не указатель, поэтому я и написал о выделении 255 байт
>под один.
>

char p = new char[ 1 ];

:)  (это по поводу 255)

Кстати кто знает может быть мне действительно нужно получить первый байт указателя? Именно поэтому компилятор выдаст только предупреждение, а не ошибку

>>свою мысль:
>>
>>Дело в том, что new возвращает указатель (на i386 это long (если
>>не ошибаюсь)) Так что при записи
>>
>>char ptr_ = new char[ SZ ];
>>
>>из-за разницы в размерах происходит потеря (truncate) 3-х старших байт. И совершенно
>>не важно чему равен SZ (хоть 10000)
>
>Естественно оператор new возвращает 4-байтный (на i386) адрес начала выделенной области памяти
>от SZ не зависящий -))
>
>>
>>Конечно в любом случае это ошибка (вероятность того, что значение указателя не
>>было при этом искажено очеееееееень мала), но надо понимать, что происходит
>>"за кадром"
>>
>>Именно из-за такого типа проблем компилятор всегда будет ругаться
>>
>>Успехов
>>--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

10. "работа с памятью"
Сообщение от David emailИскать по авторуВ закладки on 09-Июл-03, 16:26  (MSK)
>char p = new char[ 1 ];
>
>:)  (это по поводу 255)

Уважаемый sas, вы совершенно не понимаете указателей и принципа работы с ними. Когда вы пишете char p, p - это статическая переменная, под неё уже выделен один байт памяти. new char ([1] там совершенно не нужно) выделяет 1 байт в куче и возвращает 4-байтовый адрес места этого одного байта в памяти. Однобайтовой переменной типа char, очевидно, нельзя присваивать 4-байтовый указатель.
Правильная конструкция:

char *p = new char;
или
char *p = new char[255];

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

  Рекомендовать в FAQ | Cообщить модератору | Наверх

11. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 10-Июл-03, 00:18  (MSK)
Уважаемый David!

Прежде всего хотелось бы, что-бы Вы читали внимательнее ВСЕ посты входящие в обсуждение, прежде чем отвечали:

>>char p = new char[ 1 ];
>>
>>:)  (это по поводу 255)
>
>Уважаемый sas, вы совершенно не понимаете указателей и принципа работы с ними.
>Когда вы пишете char p, p - это статическая переменная, под
>неё уже выделен один байт памяти.

1) p -  НЕ СТАТИЧЕСКАЯ а автоматческая == локальная переменная Место под хранение ее значения выделяется в СТЕКЕ. Да это один байт

> new char ([1] там совершенно
>не нужно) выделяет 1 байт в куче и возвращает 4-байтовый адрес
>места этого одного байта в памяти.

Полностью с этим согласен (ниже, чтобы Вам было проще, полная копия одного из
моих предидущих сообщений):
================================================
Сообщение от sas   on        08-Июл-03, 10:22  (MSK)          

                  
>как можно выделить 255х1 байт под 1 байт?  
>char *str1 = new char[255];  

Кстати, перечитав свой и Ваш ответы, я заметил, что Вы неправильно выразили свою мысль:

Дело в том, что new возвращает указатель (на i386 это long (если не ошибаюсь)) Так что при записи

char ptr_ = new char[ SZ ];

из-за разницы в размерах происходит потеря (truncate) 3-х старших байт. И совершенно не важно чему равен SZ (хоть 10000)  

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

Именно из-за такого типа проблем компилятор всегда будет ругаться

Успехов
--- sas
=====================================================          
> Однобайтовой переменной типа char, очевидно,
>нельзя присваивать 4-байтовый указатель.
>Правильная конструкция:
>
>char *p = new char;
>или
>char *p = new char[255];
>

В принципе это правильно (см выше), однако НИКТО не мешает программисту сделать это (потерю данных) сознательно, поэтому компилятор выдает только предупреждение. Согласен, что это ПЛОХО (см выше).

Кроме того, если бы Вы дали себе труд прочитать ВСЕ, Вы бы заметили, что в данный момент обсуждается фраза:

"как можно выделить 255х1 байт под 1 байт?"

эта же фраза в принципе равна такой  

"как можно выделить 255х1 байт под 4 байт?"

Все что я хотел показать в такой строчке, с учетом небольшой иронии:

char p = new char[ 1 ] == "как можно выделить 1х1 байт под 1 байт?"

Подчеркивая, что фраза В КОРНЕ не верна (См смайлик в моем ответе после этой строки)

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

Краткая история вопроса:

Зачинатель обсуждения задал вопрос, К сожалению он так больше и не показался
В его вопросе была строка типа "char str = new char[ ... ]"  Кстати такого рода опечатки достаточно часты (и не надо убеждать меня в том, что вы их никогда не делали) При наличии такой опечатки компилятор выдаст предупреждение, которое нормальный человек игнорировать не будет за исключением РЕДЧАЙШИХ случаев

Я предположил, что задавающий вопрос, "замаскировал" переменную класса локальной переменной в конструкторе, при этом (как и автор вопроса  Copy/Paste) сделав ОПЕЧАТКУ. Прблемой это не является, тк как я уже упомянул компилятор меня бы поправил. В случае непроинициализированного члена класса компилятор НИКАКИХ предупреждений/ошибок не выдаст (по крайней мере g++ 3.1).

ЗАКЛЮЧЕНИЕ:

1 Давайте не вешать ярлыков
2 Читать ВСЕ посты внимательнее

Пункт 2 относится и ко мне тоже. Я помню свой ляп по поводу  регулярного выражения, где Вы меня поправили

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

12. "работа с памятью"
Сообщение от David emailИскать по авторуВ закладки on 10-Июл-03, 00:24  (MSK)
:))
  Рекомендовать в FAQ | Cообщить модератору | Наверх

13. "работа с памятью"
Сообщение от sas emailИскать по авторуВ закладки on 10-Июл-03, 05:49  (MSK)
>Уважаемый David!
>
>Прежде всего хотелось бы, что-бы Вы читали внимательнее ВСЕ посты входящие в
>обсуждение, прежде чем отвечали:
>
>>>char p = new char[ 1 ];
>>>
>>>:)  (это по поводу 255)
>>
>>Уважаемый sas, вы совершенно не понимаете указателей и принципа работы с ними.
>>Когда вы пишете char p, p - это статическая переменная, под
>>неё уже выделен один байт памяти.
>
>1) p -  НЕ СТАТИЧЕСКАЯ а автоматческая == локальная переменная Место
>под хранение ее значения выделяется в СТЕКЕ. Да это один байт
>
>
>> new char ([1] там совершенно
>>не нужно) выделяет 1 байт в куче и возвращает 4-байтовый адрес
>>места этого одного байта в памяти.
>
>Полностью с этим согласен (ниже, чтобы Вам было проще, полная копия одного
>из
>моих предидущих сообщений):
>================================================
>Сообщение от sas   on      
> 08-Июл-03, 10:22  (MSK)
>
>
>>как можно выделить 255х1 байт под 1 байт?  
>>char *str1 = new char[255];  
>
>Кстати, перечитав свой и Ваш ответы, я заметил, что Вы неправильно выразили
>свою мысль:
>
>Дело в том, что new возвращает указатель (на i386 это long (если
>не ошибаюсь)) Так что при записи
>
>char ptr_ = new char[ SZ ];
>
>из-за разницы в размерах происходит потеря (truncate) 3-х старших байт. И совершенно
>не важно чему равен SZ (хоть 10000)
>
>Конечно в любом случае это ошибка (вероятность того, что значение указателя не
>было при этом искажено очеееееееень мала), но надо понимать, что происходит
>"за кадром"
>
>Именно из-за такого типа проблем компилятор всегда будет ругаться
>
>Успехов
>--- sas
>=====================================================
>> Однобайтовой переменной типа char, очевидно,
>>нельзя присваивать 4-байтовый указатель.
>>Правильная конструкция:
>>
>>char *p = new char;
>>или
>>char *p = new char[255];
>>
>
>В принципе это правильно (см выше), однако НИКТО не мешает программисту сделать
>это (потерю данных) сознательно, поэтому компилятор выдает только предупреждение. Согласен, что
>это ПЛОХО (см выше).
>
>Кроме того, если бы Вы дали себе труд прочитать ВСЕ, Вы бы
>заметили, что в данный момент обсуждается фраза:
>
>"как можно выделить 255х1 байт под 1 байт?"
>
>эта же фраза в принципе равна такой
>
>"как можно выделить 255х1 байт под 4 байт?"
>
>Все что я хотел показать в такой строчке, с учетом небольшой иронии:
>
>
>char p = new char[ 1 ] == "как можно выделить 1х1
>байт под 1 байт?"
>
>Подчеркивая, что фраза В КОРНЕ не верна (См смайлик в моем ответе
>после этой строки)
>
>>А вообще - советую внимательно перечитать главу об указателях и ссылках какой-нибудь
>>хорошей книжки по сям. Это, кстати, один из самых сложных для
>>понимания моментов в этом языке.
>>Простите, если чем обидел, я хотел как лучше :)
>
>Краткая история вопроса:
>
>Зачинатель обсуждения задал вопрос, К сожалению он так больше и не показался
>
>В его вопросе была строка типа "char str = new char[ ...
>]"  Кстати такого рода опечатки достаточно часты (и не надо
>убеждать меня в том, что вы их никогда не делали) При
>наличии такой опечатки компилятор выдаст предупреждение, которое нормальный человек игнорировать не
>будет за исключением РЕДЧАЙШИХ случаев
>
>Я предположил, что задавающий вопрос, "замаскировал" переменную класса локальной переменной в конструкторе,
>при этом (как и автор вопроса  Copy/Paste) сделав ОПЕЧАТКУ. Прблемой
>это не является, тк как я уже упомянул компилятор меня бы
>поправил. В случае непроинициализированного члена класса компилятор НИКАКИХ предупреждений/ошибок не выдаст
>(по крайней мере g++ 3.1).
>
>ЗАКЛЮЧЕНИЕ:
>
>1 Давайте не вешать ярлыков
>2 Читать ВСЕ посты внимательнее
>
>Пункт 2 относится и ко мне тоже. Я помню свой ляп по
>поводу  регулярного выражения, где Вы меня поправили
>
>Успехов
>--- sas

Sorry, поправил Parish

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

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




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру