информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяСетевые кракеры и правда о деле ЛевинаЗа кого нас держат?
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Очередное исследование 19 миллиардов... 
 Оптимизация ввода-вывода как инструмент... 
 Зловреды выбирают Lisp и Delphi 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
если вы видите этот текст, отключите в настройках форума использование JavaScript
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
Ну да, естественно, не будем инициализировать внешний... 17.05.04 12:27  Число просмотров: 1537
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> может я чего не понял, но, кажется, компилятор не даст
> написать
> extern char str[] = "...";
Ну да, естественно, не будем инициализировать внешний массив. Смысл в том, чтоб внешним был не указатель а массив. Пусть будет просто extern char str[ 1 ]; ничто не мешает в другом модуле обратиться к последующим элементам.
> да и в первом случае, строка будет лежать в сегменте
> констант, поэтому
> *str = 'H';
> делать нельзя.. разве что в досе только..
Ну не писать, а читать. Пусть будет printf( "%c", *str );
> хотя надо попробовать..
>
> > Неоднозначность какая-то имеет место быть по-моему...
<programming>
[C++] посмотрите :)))) 14.05.04 14:58  
Автор: n013e Статус: Member
<"чистая" ссылка>
Сразу предупреждаю писал не я.

Методы обращения к данным

- при определении переменной интегрального типа вне функции
п-нная заносится в сегмент _BSS, обращение происходит посредством
прямой адресации памяти(например, byte ptr). инкрементирование значения
п-нной происходит через РОН.

если определить переменную вне функции с инициализацией начального
значения - п-нная заносится в _DATA.

при объявлении переменной внутри функции обращение п-нной
происходит как смещение относительно ebp, в котором находится
значение stack pointer`a для данной функции.

при объявлении глобальной переменной с модификатором volatile блок кода,
где используется данная переменная не оптимизируется

- массив

при объявлении массива вне функции без указания размерности добавляется модификатор
EXTRN, обращение к ячейкам массива происходит через идентификатор массива плюс смещение

в опт режиме цикл с обращениями к такому массиву раскладывается по отдельным итерациям.
(такая оптимизация происходит при малом значении итераций).

если объявить массив вне функции с указанием его длины, то массив помещается в сегмент
_BSS.

при объявлении указателя вне функции, ук-ль заносится в _BSS(в случае если этот ук-ль
не инициализируется или если ему присваивается значение оператора new). Если
присвоить указателю числовую константу - в _DATA. при обращении к ячейки памяти происходит
копирование значения указателя из памяти в регистр(например, есх или еах) и далее
запись/чтение через значение этого регистра с соответствующим сдвигом.

при объявлении массива без размерности в функции компилятор выдает ошибку. Если
инициализировать значение длины массива, то выделяется место в стеке (значение stack
pointer`a смещается на n*размер данных). при обращении к массиву используется
адресация по базе со смещением.

- поля структур

при объявлении структуры вне функции, она помещается в _BSS, если неинициализирована,
и в _DATA при задании начальных значений. в обоих случаях обращение к структуре
происходит посредством прямой адресации плюс смещение от начала структуры в зависимости
от поля. если структуру объявить с модификатором const, то она будет помещена в
CONST.

если структура объявлена внутри функции, то ст-ра размещается в стеке и обращение к полям
происходит относительно ebp.

при передаче структуры в качестве параметра через ссылку - передается
адрес(lea).

- члены классов

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

когда доступ к полю объекта осуществляется в функции(объект передается как параметр),
объект полностью кладется в стек в качестве аргумента(если объект объявлен внутри функции,
то при вызове функции происходит повторное копирование объекта в стеке, либо если
объект объявлен вне функции, то происходит копирование из _DATA либо _BSS в стек).
в функции обращение к полям относительно ebp.

при наличии виртуальных методов в классе, вначало каждого объекта помещается
адрес таблицы виртуальных методов(4 байта).
вызов виртуального метода:

- в регистр есх кладется адрес объекта(this).
- регистр(например, еах или еdх) заносится значение адреса ТВМ
и далее вызов ВМ командой call,

в данном случае (при наличии таблицы) первое поле объекта расположено за таблицей,
поэтому доступ к полю осуществляется с некоторым сдвигом от адреса объекта.
соответственно такое смещение не менее 4.
скажем, если имеется класс:

class base {
public:
char Char1;
virtual void Func1()
{
...
}
virtual void Func2()
{
...
}
};

то при обращении ко второму ВМ будет сгенерировано:

mov ecx, DWORD PTR _b$[ebp] ;адрес объекта в есх
mov edx, DWORD PTR [ecx] ;первые 4 байта (адрес ТВМ) в edx
mov ecx, DWORD PTR _b$[ebp] ;this в ecx
call DWORD PTR [edx+4] ;вызов виртуального метода,
;т.к. метод второй то смещение в таблице 4

далее, при обращении к полю Char1

mov eax, DWORD PTR _b$[ebp] ;адрес объекта в есх
mov BYTE PTR [eax+4], 78 ;заносим значение в байт (адрес объекта+4),
;(с учетом ТВМ)

если определить класс как:
class base {
public:
char Char1;

};

то оператор sizeof возвратит значение 1.
если :
class base {
public:
char Char1;
virtual void Func1()
{
...
}
virtual void Func2()
{
...
}
};
то sizeof возвратит 8.

без объявления виртуальных методов обращение к полям осуществляется от
адреса объекта(т.е. без дополнительного смещения на 4 байта).


P.S. писал не я
а чего, примерно так оно всё и есть.. только написано как-то криво.. 14.05.04 16:15  
Автор: zelych Статус: Member
<"чистая" ссылка>
особенно не вчитывался, но по поводу что в какие сегменты кладётся - вроде правильно..

ЗЫЖ почему-то вспомнилась заморочка от макара:
чем отличается

void f()
{
char *str1 = "hello world";
// от
char str2[] = "hello world";
// ...
}
это и есть фишка от макара... ромина пятая лаба... он просто... 14.05.04 22:04  
Автор: n013e Статус: Member
<"чистая" ссылка>
это и есть фишка от макара... ромина пятая лаба... он просто писал этот отчёт будучи под воздествием веществ, искажающих его восприятие мира..... макар его минут 20 распекал, что рома писать не умет :), он обиделся и попросил что-бы его художества оценили :)
... 21.05.04 00:25  
Автор: chill Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> это и есть фишка от макара... ромина пятая лаба... он
> просто писал этот отчёт будучи под воздествием веществ,
> искажающих его восприятие мира..... макар его минут 20
> распекал, что рома писать не умет :), он обиделся и /|\
> попросил что-бы его художества оценили :) |
|
прошу принять во внимание при прочтении сего сообщения | следующие несколько фактов, которые
не были указаны достопочтеннейшим г-ном noiZe, но которые стоят того, чтобы их изложили:
1. прежде всего это то, что все имена вымышлены. Таких людей (рома,макар) никогда не существовало
на планете Земля и всякое сходство является только случайностью и не более того.
2. хим вещества не являются чем то противоречащим конституции и законодательству РФ
3. никакой рома не обижался никакого макара (прошу особо отметить этот пункт).
Здесь-то под многими системами разницы не будет ни какой,... 14.05.04 16:47  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> особенно не вчитывался, но по поводу что в какие сегменты
> кладётся - вроде правильно..
>
> ЗЫЖ почему-то вспомнилась заморочка от макара:
> чем отличается
>
> void f()
> {
> char *str1 = "hello world";
> // от
> char str2[] = "hello world";
> // ...
> }
Здесь-то под многими системами разницы не будет ни какой, правда под Линуксом возникнет ошибка во время выполнения если написать str1[ 0 ] = 'H', а при выполнении str2[ 0 ] = 'H' ошибки не возникнет.
Раз уж зашла тема про массивы и указатели, напишу про один вопросик, который до сих пор не разрешен и покоя мне не дает. В двух разных модулях используется один массив, в одном описан, в другом определен:
char str[] = "hello, world.";
в одном, а в другом
extern char *str;
Причем, естественно extern может присутствовать в первом, и, естественно, отсутствовать во втором. Работа с массивом компилироваться должна с точки зрения языка одиннаково исходя из равнозначности описания и по разному исходя из здравого смысла. А именно оператор *str = 'H' должен дать разные коды для корректной работы.
1)
lea bx, str
mov byte ptr[bx], 'H'
или
mov bx, offset str
mov byte ptr[bx], 'H'
или
mov al, 'H'
mov str, al
если str определен как
str db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0
или
str label byte
db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0
2)
mov bx, str
mov byte ptr[bx], 'H'
если str описан как
str dw tmp
tmp db 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.', 0

Неоднозначность какая-то имеет место быть по-моему...
не, у загадки есть более интерестное решение.. 15.05.04 00:50  
Автор: zelych Статус: Member
<"чистая" ссылка>

...
> дает. В двух разных модулях используется один массив, в
> одном описан, в другом определен:
> char str[] = "hello, world.";
> в одном, а в другом
> extern char *str;
> Причем, естественно extern может присутствовать в первом,
> и, естественно, отсутствовать во втором. Работа с массивом

может я чего не понял, но, кажется, компилятор не даст написать
extern char str[] = "...";
да и в первом случае, строка будет лежать в сегменте констант, поэтому
*str = 'H';
делать нельзя.. разве что в досе только..
хотя надо попробовать..

> Неоднозначность какая-то имеет место быть по-моему...
собственно, отгадка.. 19.05.04 16:22  
Автор: zelych Статус: Member
<"чистая" ссылка>
много писать не буду, поскольку никто слишком не интересовался..

f1() () at c.cpp:5 5 char str[] = "hello world?????"; (gdb) disassemble Dump of assembler code for function _Z2f1v: 0x8048300 <_Z2f1v>: push %ebp 0x8048301 <_Z2f1v+1>: mov %esp,%ebp 0x8048303 <_Z2f1v+3>: push %edi 0x8048304 <_Z2f1v+4>: push %esi 0x8048305 <_Z2f1v+5>: sub $0x20,%esp 0x8048308 <_Z2f1v+8>: lea 0xffffffd8(%ebp),%edi 0x804830b <_Z2f1v+11>: mov $0x804845c,%esi 0x8048310 <_Z2f1v+16>: cld 0x8048311 <_Z2f1v+17>: mov $0x11,%ecx 0x8048316 <_Z2f1v+22>: repz movsb %ds:(%esi),%es:(%edi) 0x8048318 <_Z2f1v+24>: add $0x20,%esp 0x804831b <_Z2f1v+27>: pop %esi 0x804831c <_Z2f1v+28>: pop %edi 0x804831d <_Z2f1v+29>: leave 0x804831e <_Z2f1v+30>: ret End of assembler dump. (gdb) x/s 0x804845c 0x804845c <_IO_stdin_used+4>: "hello world?????" 10 char *str = "hello world!!!!!"; (gdb) disassemble Dump of assembler code for function _Z2f2v: 0x8048320 <_Z2f2v>: push %ebp 0x8048321 <_Z2f2v+1>: mov %esp,%ebp 0x8048323 <_Z2f2v+3>: sub $0x4,%esp 0x8048326 <_Z2f2v+6>: movl $0x804846d,0xfffffffc(%ebp) 0x804832d <_Z2f2v+13>: leave 0x804832e <_Z2f2v+14>: ret End of assembler dump. (gdb) x/s 0x804846d 0x804846d <_IO_stdin_used+21>: "hello world!!!!!"

если кто ещё не понял - разница принципиальная..
если у вас в цикле много раз вызывается функция с такой вот строчкой:

char str[] = "very very long string";

то это не есть хорошо
Ну да, естественно, не будем инициализировать внешний... 17.05.04 12:27  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> может я чего не понял, но, кажется, компилятор не даст
> написать
> extern char str[] = "...";
Ну да, естественно, не будем инициализировать внешний массив. Смысл в том, чтоб внешним был не указатель а массив. Пусть будет просто extern char str[ 1 ]; ничто не мешает в другом модуле обратиться к последующим элементам.
> да и в первом случае, строка будет лежать в сегменте
> констант, поэтому
> *str = 'H';
> делать нельзя.. разве что в досе только..
Ну не писать, а читать. Пусть будет printf( "%c", *str );
> хотя надо попробовать..
>
> > Неоднозначность какая-то имеет место быть по-моему...
забавный эффект получается.. 19.05.04 16:14  
Автор: zelych Статус: Member
<"чистая" ссылка>
если взять два файлика:
--- a.c ---
#include <stdio.>

extern char str[];

void main()
{
    puts( str );
}

--- b.c ---
char *str = "hello world"


---
то в качестве аргумента puts передаётся адрес указателя на строку:
0x8048343 <main+19>:    push   $0x8049474
0x8048348 <main+24>:    call   0x8048254 <puts>
...
(gdb) x 0x8049474
0x8049474 <str>:        0x0804845c
(gdb) x/s 0x804845c
0x804845c <_IO_stdin_used+4>:    "hello world"

---

соответственно, печатается не hello world, а мусор..
если в b.c написать str[] = "hello world", тогда всё окей, выводится сама строка..
и наоборот, тобишь тип должен быть одинаковым в обеих файлах..

вопрос! почему тогда компилятор не ругается на несоответствие типов?
испытания проводились под gcc, выжалстудию, и интеловский компилятор.. результат одинаковый
Ну я примеры не приводил, а только описал. В том-то и дело,... 20.05.04 14:30  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 20.05.04 14:31  Количество правок: 1
<"чистая" ссылка>
> соответственно, печатается не hello world, а мусор..
> если в b.c написать str[] = "hello world", тогда всё окей,
> выводится сама строка..
> и наоборот, тобишь тип должен быть одинаковым в обеих
> файлах..
>
> вопрос! почему тогда компилятор не ругается на
> несоответствие типов?
> испытания проводились под gcc, выжалстудию, и интеловский
> компилятор.. результат одинаковый

Ну я примеры не приводил, а только описал их. В том-то и дело, что везде описано, что str[] и *str идентичны! А на деле-то совсем не так. Мало того и не может быть так. Ну а не ругается, потому что по правилам языка типы то соответствуют.
непонятно как-то.. 20.05.04 15:44  
Автор: zelych Статус: Member
<"чистая" ссылка>

> Ну я примеры не приводил, а только описал их. В том-то и
> дело, что везде описано, что str[] и *str идентичны! А на

в том-то и дело, что не идентичны..
то, что описано в другом моём посте - это в соответствии со стандартом


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

просто какое-то не совсем логичное поведение компиляторов..

http://www.bugtraq.ru/cgi-bin/forum.mcgi?type=sb&b=2&m=104939
И я говорю, что на практике не идентичны, а в соответствии... 20.05.04 16:29  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> в том-то и дело, что не идентичны..
> то, что описано в другом моём посте - это в соответствии со
> стандартом

И я говорю, что на практике не идентичны, а в соответствии со стандартом должны быть идентичны.

> просто какое-то не совсем логичное поведение компиляторов.

Как же не логичное. Компиляторы генерят код по описанию. Просто в стандарте надо указать, что *str и str[] совершенно разные вещи! Только для удобства программеров сделано так, что обращение к элементам по *str и str[ 0 ] эквивалентны, как и циклическая обработка векторов по *str++ и str[ i++ ], где, разумеется, в первом случае изменяется сам указатель, а во втором только индекс, и, опять же, первая конструкция совсем не применима, если str был описан как массив, а не указатель.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach