What is the "slicing phenomenon" when trying to read data from a heterogeneous array?

Asked

Viewed 121 times

7

I was curiously reading a reply on how to store heterogeneous types in an array when I come across the following response snippet:

You will have to store in each element of the vector the object and of what type it is, and deal with each element according to the type. Without this it runs the risk of taking an object as if it were another with an inadequate structure. This phenomenon is called slicing.

I interpreted here that slicing would be the inadequate "cutting" of information in the vector, making the object obtained through these bytes at best does not make sense. My interpretation was something like this:

Bytes separados por objetos reais
| b0   b1   b2 | b3   b4 | b5   b6 |
Slicing decorrente da leitura errada
| b0   b1 | b2   b3   b4 | b5   b6 |

The first two objects read differ from reading correctly and reading with slicing.

So my doubts are:

  • This interpretation above is correct?

  • The problem of slicing seems to happen also in C for the same reasons; in which languages* is it most apparent? Has virtually shielded languages against this effect?

  • The slicing may occur within a homogeneous data vector? Or it is restricted to heterogeneous data?

    *: does not need to be an exhaustive list, it would be sufficient to define which languages follow the characteristic x are susceptible to this phenomenon

  • 1

    I did not want to go into details there, the question is very pertinent here, I will explain better the phenomenon.

1 answer

7


Slicing exists in various contexts of computing. I am talking about the Slice of an object. This usually happens in object-oriented languages. There the example was in vector, but not confused with the slicing of data collections which is something deliberate that the programmer has done. I’m talking about something that happens inadvertently in objects.

This interpretation above is correct?

That’s the idea, but not exactly like this, at least within what I know. It may even be that this may occur in some situation, but I’ve never seen something like the one shown (it may be my ignorance).

The slicing usually happens between types with inheritance relationship.

The problem of slicing seems to happen also in C for the same reasons; in which languages* is it most apparent? Has virtually shielded languages against this effect?

The phenomenon occurs inadvertently in weak typing languages (not to be confused with dynamic typing). Of course, in strong typing languages it is possible to reproduce the phenomenon if it explicitly allows you to change the type of an object without a conversion. This is rare in modern languages, even if Compile when doing this should give an error and it is not enough to present the slicing. By modern languages understand as managed languages. In a way only these languages can be considered completely strong in typing, but this is another subject.

C is a weak typing language and could occur, but it has no inheritance relation. Similar and even more serious problems would occur if the code really wanted to, but not exactly the slicing. The example shown in the question does something more serious, but for it to occur it takes some effort ;) The code has to ask for it to occur.

In C, and to some extent in C++, depending on the encoding style, it can corrupt memory, which is worse than the slicing, that wouldn’t even occur.

The slicing may occur within a homogeneous data vector? Or it is restricted to heterogeneous data?

Really homogeneous can not. Except for a deficiency of language implementation, but I dismiss this.

How does the slicing.

The slicing occurs when you wait for an object and come another with extended structure.

By structure understand the state. The slicing is not about behaviors, so if a derivative type adds nothing to the base object, you are free of the slicing. Some will say that in this case there was even a de facto inheritance.

Let’s see:

class Base
    x : int

class Derivada : Base
    y : int

b := Base()
d := Derivada() { x = 1, y = 2 }
b = d //funciona porque d é do tipo de b, nem toda linguagem deixa implicitamente
print b.x //sem problemas, dá 1
//print b.y //daria erro porque em b não tem y, então não temos problema aqui
d = b
print d.x //beleza, dá 1
print d.y //agora pode, d tem um y, mas imprime 2?

I put in the Github for future reference.

It turns out that b does not have the element y, he loses himself, when he turns and puts b in the derivative type only x exists, the y would have a value default (probably), there happens the slicing in the b = d.

In a vector there is an assignment like this. If Vector<Base> is used when you do v[0] = d is doing the same as b = d, occurs the slicing. In each variable of v only room for the type Base, I mean, there’s only room for one int, when you try to put a type that is considered compatible there but it has more data, these will be discarded, then the d who had two intyou will lose the second.

That is why it is recommended to avoid the use of types per value unless there are clear gains, are obviously basic values immutable or you need a lot of optimization and know a lot what you are doing and understand all the phenomena that can occur, among them the "quartering" (the term should not be slashing?).

When you wear one type by reference or deals with one type per value as reference the problem does not occur because of the indirect.

In these types the basic stored value is a pointer always the same size, never occurs the slicing. The die really is somewhere else and can be different sizes. Of course in completely strong typing languages all will be of the same basic type (without covariance can leak).

Remembering that there are several forms of assignment (copy), one of them is to pass a data to a function. When it is passed by reference the copy is only of the pointer and not of the object itself, then we can say that there is a change and not a copy. Only the copy of the object can shred it.

Another way to solve this is to create a copy builder that deals with the issue properly, but does not always compensate.

Note that this case I exemplified is not a real problem because the compiler does not let it. Even in C++ in the way you do it doesn’t have to go wrong. Now what can go wrong and you realize too late:

struct A {
    A(int a) : a_var(a) {}
    int a_var;
};

struct B : public A {
    B(int a, int b) : A(a), b_var(b) {}
    int b_var;
};

B &getB() { //importante o retorno por referência
    static B b(1, 2);
    return b;
}

int main() {
    A a(3);
    a = getB();
    // a.a_var == 1, b.b_var não copiado para a
    B b2(3, 4);
    A &a2 = b2;
    a2 = getB();
    cout << b2.a_var << b2.b_var; //dá 1 e 4, misturou os objetos
}

I put in the Github for future reference.

Wikipedia.

Most languages do not suffer from this. C++ is too high and too low a level, this combination causes the problem. The slicing occurs in several languages, but the compiler identifies and prohibits.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.