Как я объявляю, что массив создал использование malloc, чтобы быть энергозависимым в C++

Я предполагаю, что следующее даст мне 10 энергозависимых ints

volatile int foo[10];

Однако я не думаю, что следующее сделает то же самое.

volatile int* foo;
foo = malloc(sizeof(int)*10);

Исправьте меня, если я неправ относительно этого и как у меня может быть энергозависимый массив объектов с помощью malloc.

Спасибо.

15
задан Mark 21 February 2010 в 04:09
поделиться

5 ответов

int volatile * foo;

читается справа налево «foo - указатель на изменчивый int»

, поэтому к любому int, к которому вы обращаетесь через foo, int будет непостоянным.

P.S.

int * volatile foo; // "foo is a volatile pointer to an int"

==

volatile int * foo; // foo is a pointer to an int, volatile

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

char const * foo;

вместо более распространенного

const char * foo;

. Если вы хотите большего такие сложные вещи, как «указатель на функцию, возвращающую указатель на int», имеют какой-то смысл.

P.S., И это большая проблема (и основная причина, по которой я добавляю ответ):

Я заметил, что вы включили «многопоточность» в качестве тега. Понимаете ли вы, что volatile не дает ничего хорошего в отношении многопоточности?

13
ответ дан 1 December 2019 в 02:55
поделиться

PyLog :

PyLog является логической библиотекой первого порядка включая модуль PROLOG в Python.

-121--2964652-

Обычно рекомендуется сделать это в onCreate () / onDestroy () или onStart () / onStop () , в зависимости от желаемой семантики:

  • Если операция должна взаимодействовать с услугой в течение всего времени ее работы (например, он может получить некоторые данные из сети для вас и вернет данные, когда они будут готовы, и вы хотите, чтобы это произошло в фоновом режиме, так что если пользователь вернет вы будете готовы данные), то onCreate () / onDestroy () , вероятно, подходит. Следует отметить, что семантика состоит в том, что в течение всего времени выполнения операции требуется Сервис , поэтому, если Сервис выполняется в другом процессе, вес этого процесса увеличивается, что повышает вероятность его уничтожения в фоновом режиме.

  • Если функция Activity предназначена только для работы со службой Service во время отображения, то onStart () / onStop () является подходящей. Это означает, что операция отменяет привязку к услуге , когда пользователь покидает ее (и она больше не видна), и выполняет резервное копирование при следующем возврате, а затем повторно запускается и возобновляется.

Обычно не рекомендуется выполнять привязку/отмену привязки в onResume () и onPause () . Это, как правило, значительно не уменьшает количество, которое вы используете Сервис (и, следовательно, ваши накладные расходы), и фактически, поскольку пауза и возобновление происходят при каждом переходе активности, это путь кода, который вы хотите сохранить как можно более легким. Это может иметь и другие неожиданные негативные последствия: например, если несколько действий в приложении привязываются к одной и той же службе , то при переходе между двумя из этих действий служба также может быть уничтожена и воссоздана, поскольку текущее действие приостановлено перед возобновлением следующего.

Также эти пары ( onCreate () / onDestroy () , onStart () / onStop () , onPause () / onResume () ) предназначены, чтобы быть надлежащими парами для приобретения и затем высвободить средства (такие как соединение с Обслуживание с, регистрация приемников, и т.д.), чтобы гарантировать, что они правильно приобретены до того, чтобы быть необходимым и выпущены (и не пропущены), когда больше не необходимый.

-121--1650847-
volatile int* foo;

- это путь. Квалификатор типа volatile работает так же, как квалификатор типа const . Если бы вам нужен был указатель на постоянный массив целых чисел, вы бы написали:

const int* foo;

, тогда как

int* const foo;

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

6
ответ дан 1 December 2019 в 02:55
поделиться

Да, это сработает. Нет ничего особенного в фактической памяти, которая является энергозависимой . Это просто способ сообщить компилятору, как взаимодействовать с этой памятью.

3
ответ дан 1 December 2019 в 02:55
поделиться

Я думаю, что второй объявляет указатель изменчивым, а не то, на что он указывает. Чтобы получить это, я думаю, он должен быть

int * volatile foo;

Этот синтаксис приемлем для gcc , но мне трудно убедить себя , что он делает что-то другое.

Я обнаружил разницу с gcc -O3 (полная оптимизация).Для этого (глупого) тестового кода:

volatile int  v [10];
int * volatile p;

int main (void)
{
        v [3] = p [2];
        p [3] = v [2];
        return 0;
}

С volatile и опусканием (x86) инструкций, которые не меняются:

    movl    p, %eax
    movl    8(%eax), %eax
    movl    %eax, v+12
    movl    p, %edx
    movl    v+8, %eax
    movl    %eax, 12(%edx)

Без volatile, он пропускает перезагрузку p :

    movl    p, %eax
    movl    8(%eax), %edx    ; different since p being preserved
    movl    %edx, v+12
    ; 'p' not reloaded here
    movl    v+8, %edx
    movl    %edx, 12(%eax)   ; p reused

После множества научных экспериментов, пытающихся найти разницу, я пришел к выводу, что разницы нет. volatile отключает все оптимизации, связанные с переменной, которая будет повторно использовать впоследствии установленное значение. По крайней мере, с x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33). : -)

2
ответ дан 1 December 2019 в 02:55
поделиться

Выполните следующие действия:

int showLimit = 20;

/* Get all Tasks available (with limit set). */
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks) 
{                  
    Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName()); 
    if (aTask.baseActivity.getClassName().equals("com.android.email.activity.MessageList")) 
        running=true;
}
-121--731745-
var firstImage = imgList.Cast<Image>().First();
-121--1712600-

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

с помощью кода: и компиляции с -03

int main (void)
{
        while(p[2]);
        return 0;
}

, когда p просто объявлен как указатель, мы застрянем в цикле, из которого невозможно выбраться. Заметим, что если бы это была многопоточная программа и другой поток записывал p [2] = 0, то программа вырвалась бы из цикла while и завершилась бы нормально.

int * p;
============
LCFI1:
        movq    _p(%rip), %rax  
        movl    8(%rax), %eax   
        testl   %eax, %eax
        jne     L6              
        xorl    %eax, %eax
        leave
        ret
L6:
        jmp     L6

обратите внимание, что единственной инструкцией для L6 является переход к L6.

=

, когда p является энергозависимым указателем

int * volatile p;
==============
L3:
        movq    _p(%rip), %rax
        movl    8(%rax), %eax
        testl   %eax, %eax
        jne     L3
        xorl    %eax, %eax
        leave
        ret 

, указатель p перегружается на каждую итерацию цикла, и, как следствие, массив предмета также перезагружается. Однако, это было бы неправильно, если бы мы хотели массив изменчивых целых чисел, так как это было бы возможно:

int* volatile p;
..
..
int* j;
j = &p[2];
while(j);

и привело бы к циклу, который было бы невозможно завершить в многопоточной программе.

= =

наконец, это правильное решение, как хорошо объяснили Тони.

int volatile * p;
LCFI1:
        movq    _p(%rip), %rdx
        addq    $8, %rdx
        .align 4,0x90
L3:
        movl    (%rdx), %eax
        testl   %eax, %eax
        jne     L3
        leave
        ret 

В этом случае адрес p [2] сохраняется в регистровом значении и не загружается из памяти, но значение p [2] перезагружается из памяти в каждом цикле цикла.

также следует отметить, что

int volatile * p;
..
..
int* j;
j = &p[2];
while(j);

создаст ошибку компиляции.

1
ответ дан 1 December 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: